From 4d4dee54e51c574236474147eb2fe51355d7dd98 Mon Sep 17 00:00:00 2001 From: simp Date: Fri, 19 Sep 2025 20:02:43 +0000 Subject: [PATCH] parsing improvements for terminus.i2p and gitea rss feeds, separate clean channel for clearnet bridging --- app.py | 2851 ++++++++++++++++++++++-------------------- changelognewsbot.txt | 3 + functions.py | 2 +- rsslist.txt | 54 +- 4 files changed, 1516 insertions(+), 1394 deletions(-) diff --git a/app.py b/app.py index 243f24c..018aebf 100755 --- a/app.py +++ b/app.py @@ -24,98 +24,98 @@ feed_url = {} ############ def external_site_status_infos(site_list, online, offline, site_type, make_list, days): - online_links = [] - online_list_links = [] - time_date_format = '%Y-%m-%d %H:%M:%S.%f' - online_list_links.append('
')
-    first_run = True
-    online_count = 0
-    offline_count = 0
-    for item in site_list:
-        if site_type == 'all' and make_list == True:
-            site = Sites.query.filter_by(site_id=item).first()
-            if site:
-                last_seen = site.last_seen
-                if last_seen != '0':
-                    time_obj = datetime.strptime(last_seen, time_date_format)
-                    last_seen_str = time_obj.strftime('%d-%m-%Y')
-                    time_now_obj = datetime.now()
-                    difference = time_now_obj - time_obj
-                    one_week = timedelta(days=days)
-                    if difference < one_week:
-                        online_count += 1
-                        online_list_links.append(f'
{item}
') - else: - offline_count += 1 - else: - offline_count += 1 + online_links = [] + online_list_links = [] + time_date_format = '%Y-%m-%d %H:%M:%S.%f' + online_list_links.append('
')
+	first_run = True
+	online_count = 0
+	offline_count = 0
+	for item in site_list:
+		if site_type == 'all' and make_list == True:
+			site = Sites.query.filter_by(site_id=item).first()
+			if site:
+				last_seen = site.last_seen
+				if last_seen != '0':
+					time_obj = datetime.strptime(last_seen, time_date_format)
+					last_seen_str = time_obj.strftime('%d-%m-%Y')
+					time_now_obj = datetime.now()
+					difference = time_now_obj - time_obj
+					one_week = timedelta(days=days)
+					if difference < one_week:
+						online_count += 1
+						online_list_links.append(f'
{item}
') + else: + offline_count += 1 + else: + offline_count += 1 - if site_list[item]['category'] == site_type: - if first_run == True: - online_links.append(f"") - first_run = False - site = Sites.query.filter_by(site_id=item).first() - if site: - last_seen = site.last_seen - ping_ms = float(site.ping) - if ping_ms == 0: - ping = f'-' - else: - ping = f'{str(ping_ms)}ms' - # print(last_seen) - if last_seen != '0': - time_obj = datetime.strptime(last_seen, time_date_format) - last_seen_str = time_obj.strftime('%d-%m-%Y') - else: - last_seen_str = "Never" - if site.online.lower() == "online": - status = f"{online} " - span1 = '' - span2 = '' - online_count += 1 - else: - status = f"{offline} " - span1 = '' - span2 = '' - offline_count += 1 - if make_list == True: - if last_seen != '0': - time_now_obj = datetime.now() - difference = time_now_obj - time_obj - one_week = timedelta(days=days) - if difference < one_week: - online_list_links.append(f'
{item}
') - else: - online_list_links_s = '' - else: - status = '' - span1 = '' - span2 = '' - ping = '' - last_seen_str = '' - site_name = ((item.split("//")[1]).split('/'))[0] - try: - if len(site_name) > 30: - site_name = f"{site_name[:12]}...{site_name[-12:]}" - except Exception as e: - print(e) - online_links.append(f'') - else: - pass - online_links.append("
SiteLast pingLast seen
{span1}
{status}
{span2}
{ping}{last_seen_str}
") - online_links_s = ''.join(online_links) - if make_list == True: - online_list_links.append('
') - online_list_links_s = ''.join(online_list_links) - return(online_links_s, online_list_links_s, online_count, offline_count) + if site_list[item]['category'] == site_type: + if first_run == True: + online_links.append(f"") + first_run = False + site = Sites.query.filter_by(site_id=item).first() + if site: + last_seen = site.last_seen + ping_ms = float(site.ping) + if ping_ms == 0: + ping = f'-' + else: + ping = f'{str(ping_ms)}ms' + # print(last_seen) + if last_seen != '0': + time_obj = datetime.strptime(last_seen, time_date_format) + last_seen_str = time_obj.strftime('%d-%m-%Y') + else: + last_seen_str = "Never" + if site.online.lower() == "online": + status = f"{online} " + span1 = '' + span2 = '' + online_count += 1 + else: + status = f"{offline} " + span1 = '' + span2 = '' + offline_count += 1 + if make_list == True: + if last_seen != '0': + time_now_obj = datetime.now() + difference = time_now_obj - time_obj + one_week = timedelta(days=days) + if difference < one_week: + online_list_links.append(f'
{item}
') + else: + online_list_links_s = '' + else: + status = '' + span1 = '' + span2 = '' + ping = '' + last_seen_str = '' + site_name = ((item.split("//")[1]).split('/'))[0] + try: + if len(site_name) > 30: + site_name = f"{site_name[:12]}...{site_name[-12:]}" + except Exception as e: + print(e) + online_links.append(f'') + else: + pass + online_links.append("
SiteLast pingLast seen
{span1}
{status}
{span2}
{ping}{last_seen_str}
") + online_links_s = ''.join(online_links) + if make_list == True: + online_list_links.append('
') + online_list_links_s = ''.join(online_list_links) + return(online_links_s, online_list_links_s, online_count, offline_count) settings_path = os.path.join(script_directory, 'website.ini') lists_ini = os.path.join(script_directory, 'lists.ini') hostname, channel, primary, auth_users, news_bot, news_pass, news_port, news_rss_port, http_tunnel, news_email, gunicorn_port, bot_send, ah = config_load(settings_path) list_items = load_settings_ini(lists_ini) proxies = { - 'http': f'{hostname}:{http_tunnel}', - 'https': f'{hostname}:{http_tunnel}' + 'http': f'{hostname}:{http_tunnel}', + 'https': f'{hostname}:{http_tunnel}' } allowed_tags = '' cat_dict = { @@ -133,1367 +133,1458 @@ generate_rss_feed() rss_icon = get_svg(script_directory, 'rss') up_icon = get_svg(script_directory, 'up') go_up = f'''{up_icon}''' -footer = f'''| Running on I2P+ | TOS | Changelog | AH | Status | a snack for lateryou're still hungry?''' +footer = f''' Running on I2P+ | TOS | Changelog | AH | Donate | Status a snack for lateryou're still hungry?''' ######## #dbs ######## app.config["SQLALCHEMY_DATABASE_URI"] = "sqlite:///db3f.sqlite" app.config['SQLALCHEMY_BINDS'] = { - "sites": "sqlite:///db3f.sqlite", - "irc": "sqlite:///db3f.sqlite", - "settings": "sqlite:///db3f.sqlite", + "sites": "sqlite:///db3f.sqlite", + "irc": "sqlite:///db3f.sqlite", + "settings": "sqlite:///db3f.sqlite", } db = SQLAlchemy() class Sites(db.Model): - # __bind_key__ = 'sites' - id = db.Column(db.Integer, primary_key=True) - site_id = db.Column(db.String(1000), unique=True, nullable=False) - online = db.Column(db.String(20), nullable=True) - last_seen = db.Column(db.String(50), nullable=True) - ping = db.Column(db.String(50), nullable=True) - def __repr__(self): - return f'' + # __bind_key__ = 'sites' + id = db.Column(db.Integer, primary_key=True) + site_id = db.Column(db.String(1000), unique=True, nullable=False) + online = db.Column(db.String(20), nullable=True) + last_seen = db.Column(db.String(50), nullable=True) + ping = db.Column(db.String(50), nullable=True) + def __repr__(self): + return f'' class Irc(db.Model): - __bind_key__ = 'irc' - id = db.Column(db.Integer, primary_key=True) - user = db.Column(db.String(200), unique=True, nullable=False) - first_seen = db.Column(db.String(200), unique=False, nullable=False) - admin = db.Column(db.Boolean, unique=False, nullable=False) - banned = db.Column(db.Boolean, unique=False, nullable=False) - welcomed = db.Column(db.Boolean, unique=False, nullable=False) - approved = db.Column(db.Boolean, unique=False, nullable=False) - tracker_code = db.Column(db.String(200), unique=False, nullable=True) - invites = db.Column(db.Integer, unique=False, nullable=True) - points = db.Column(db.Integer, unique=False, nullable=True) - def __repr__(self): - return f'' + __bind_key__ = 'irc' + id = db.Column(db.Integer, primary_key=True) + user = db.Column(db.String(200), unique=True, nullable=False) + first_seen = db.Column(db.String(200), unique=False, nullable=False) + admin = db.Column(db.Boolean, unique=False, nullable=False) + banned = db.Column(db.Boolean, unique=False, nullable=False) + welcomed = db.Column(db.Boolean, unique=False, nullable=False) + approved = db.Column(db.Boolean, unique=False, nullable=False) + tracker_code = db.Column(db.String(200), unique=False, nullable=True) + invites = db.Column(db.Integer, unique=False, nullable=True) + points = db.Column(db.Integer, unique=False, nullable=True) + def __repr__(self): + return f'' class Settings(db.Model): - __bind_key__ = 'settings' - id = db.Column(db.Integer, primary_key=True) - setting = db.Column(db.String(200), unique=True, nullable=False) - number = db.Column(db.Integer, unique=False, nullable=True) - floats = db.Column(db.Float, unique=False, nullable=True) - bol = db.Column(db.Boolean, unique=False, nullable=True) - string = db.Column(db.String(200), unique=False, nullable=True) - def __repr__(self): - return f'' + __bind_key__ = 'settings' + id = db.Column(db.Integer, primary_key=True) + setting = db.Column(db.String(200), unique=True, nullable=False) + number = db.Column(db.Integer, unique=False, nullable=True) + floats = db.Column(db.Float, unique=False, nullable=True) + bol = db.Column(db.Boolean, unique=False, nullable=True) + string = db.Column(db.String(200), unique=False, nullable=True) + def __repr__(self): + return f'' db.init_app(app) with app.app_context(): - db.create_all() + db.create_all() ######## #flask ######## @app.route('/', methods = ['GET']) def home(): - hl = header_links_update(links_dict, 0) - topic = 'all' - list_md = os.path.join(script_directory, 'static/rssfeed/') - file_list, body_preview, file_name = logger_list(list_md, True) - file = os.path.join(script_directory, 'md_files/newsbot/feedbanner.md') - try: - with open(file, 'r') as f: - tempMd= f.read() - top_body = markdown.markdown(tempMd) - except (FileNotFoundError) as e: - top_body = 'ERROR - no content found for this!' - - if topic in file_name: - title = 'RSS Feeds' - logger_line_list = [] - txt_file = os.path.join(script_directory, f'static/rssfeed/{topic}.txt') - file_object_r = open(txt_file, 'r') - read_file_r = file_object_r.read() - logger_line_list = read_file_r.splitlines(True) - file_object_r.close() - formatted_list = [] - for item in logger_line_list: - if len(item)>2: - formatted_msg = format_msg(item, topic) - if formatted_msg != '': - formatted_list.append(formatted_msg) - formatted_list.reverse() - body = '
'.join(formatted_list) - else: - body = 'NOT FOUND' - title = 'RSS Feeds' - blog_posts_links = [] - w = 1 - feed_html = f'''''' - b = len(file_list) - for x in range(0, b): - blog_posts_links.append(f'''{str(b)}. {file_name[x].title()}
''') - w += 1 - b -= 1 - blog_posts_links.append(f'Categories {feed_html}
') - chan_list_links = ''.join(blog_posts_links[::-1]) - blog_body = f'
{chan_list_links}
{top_body}
{body}
' - # blog_body = f'
{chan_list_links}
{body}
' - return render_template('md_file.html', footer=footer, body=blog_body, title=title, header_links=hl, go_up=go_up) + hl = header_links_update(links_dict, 0) + topic = 'all' + list_md = os.path.join(script_directory, 'static/rssfeed/') + file_list, body_preview, file_name = logger_list(list_md, True) + file = os.path.join(script_directory, 'md_files/newsbot/feedbanner.md') + try: + with open(file, 'r') as f: + tempMd= f.read() + top_body = markdown.markdown(tempMd) + except (FileNotFoundError) as e: + top_body = 'ERROR - no content found for this!' + + if topic in file_name: + title = 'RSS Feeds' + logger_line_list = [] + txt_file = os.path.join(script_directory, f'static/rssfeed/{topic}.txt') + file_object_r = open(txt_file, 'r') + read_file_r = file_object_r.read() + logger_line_list = read_file_r.splitlines(True) + file_object_r.close() + formatted_list = [] + for item in logger_line_list: + if len(item)>2: + formatted_msg = format_msg(item, topic) + if formatted_msg != '': + formatted_list.append(formatted_msg) + formatted_list.reverse() + body = '
'.join(formatted_list) + else: + body = 'NOT FOUND' + title = 'RSS Feeds' + blog_posts_links = [] + w = 1 + feed_html = f'''''' + b = len(file_list) + for x in range(0, b): + blog_posts_links.append(f'''{str(b)}. {file_name[x].title()}
''') + w += 1 + b -= 1 + blog_posts_links.append(f'Categories {feed_html}
') + chan_list_links = ''.join(blog_posts_links[::-1]) + blog_body = f'
{chan_list_links}
{top_body}
{body}
' + # blog_body = f'
{chan_list_links}
{body}
' + return render_template('md_file.html', footer=footer, body=blog_body, title=title, header_links=hl, go_up=go_up) @app.route('/category/', methods = ['GET']) def feed_cat(input_string): - sanitized = sanitize_input(input_string) - hl = header_links_update(links_dict, 0) - topic = sanitized - if len(sanitized) > 24: - abort(404) - list_md = os.path.join(script_directory, 'static/rssfeed/') - file_list, body_preview, file_name = logger_list(list_md, True) - if topic in file_name: - title = 'RSS Feeds' - logger_line_list = [] - txt_file = os.path.join(script_directory, f'static/rssfeed/{topic}.txt') - file_object_r = open(txt_file, 'r') - read_file_r = file_object_r.read() - logger_line_list = read_file_r.splitlines(True) - file_object_r.close() - formatted_list = [] - for item in logger_line_list: - if len(item)>2: - formatted_msg = format_msg(item, topic) - if formatted_msg != '': - formatted_list.append(formatted_msg) - formatted_list.reverse() - body = '
'.join(formatted_list) - else: - body = 'NOT FOUND' - title = 'RSS Feeds' - blog_posts_links = [] - w = 1 - if topic == 'all': - feed_url = '/feed' - else: - feed_url = f'/feed/{topic}' - feed_html = f'''''' - b = len(file_list) - for x in range(0, b): - blog_posts_links.append(f'''{str(b)}. {file_name[x].title()}
''') - w += 1 - b -= 1 - blog_posts_links.append(f'Categories {feed_html}
') - chan_list_links = ''.join(blog_posts_links[::-1]) - blog_body = f'
{chan_list_links}
{body}
' - return render_template('md_file.html', footer=footer, body=blog_body, title=title, header_links=hl, go_up=go_up) + sanitized = sanitize_input(input_string) + hl = header_links_update(links_dict, 0) + topic = sanitized + if len(sanitized) > 24: + abort(404) + list_md = os.path.join(script_directory, 'static/rssfeed/') + file_list, body_preview, file_name = logger_list(list_md, True) + if topic in file_name: + title = 'RSS Feeds' + logger_line_list = [] + txt_file = os.path.join(script_directory, f'static/rssfeed/{topic}.txt') + file_object_r = open(txt_file, 'r') + read_file_r = file_object_r.read() + logger_line_list = read_file_r.splitlines(True) + file_object_r.close() + formatted_list = [] + for item in logger_line_list: + if len(item)>2: + formatted_msg = format_msg(item, topic) + if formatted_msg != '': + formatted_list.append(formatted_msg) + formatted_list.reverse() + body = '
'.join(formatted_list) + else: + body = 'NOT FOUND' + title = 'RSS Feeds' + blog_posts_links = [] + w = 1 + if topic == 'all': + feed_url = '/feed' + else: + feed_url = f'/feed/{topic}' + feed_html = f'''''' + b = len(file_list) + for x in range(0, b): + blog_posts_links.append(f'''{str(b)}. {file_name[x].title()}
''') + w += 1 + b -= 1 + blog_posts_links.append(f'Categories {feed_html}
') + chan_list_links = ''.join(blog_posts_links[::-1]) + blog_body = f'
{chan_list_links}
{body}
' + return render_template('md_file.html', footer=footer, body=blog_body, title=title, header_links=hl, go_up=go_up) @app.route('/feedlinks', methods = ['GET']) def status(): - hl = header_links_update(links_dict, 0) - topic = 'RSS Feed Links' - lines_list = [] - title = 'RSS Feeds' - info = get_svg(script_directory, 'info') - online = get_svg(script_directory, 'online') - offline = get_svg(script_directory, 'offline') - contact = f'

Send me a message if you want yours added: {news_email}

' - body_list = [] - links, w, on, off = external_site_status_infos(feed_url, online, offline, 'all', True, days) - body_list.append(f'''

All Alive Feeds | {str(on)}/{str(on + off)} seen recently [JSON]

Seen in last {str(days)} days (all sites){w}
''') - for item in cat_dict: - links, w, on, off = external_site_status_infos(feed_url, online, offline, item, True, days) - heading = f'

{cat_dict[item]}' - body_list.append(f'''{heading}{links}
Seen in the last {str(days)} days{w}
''') - body = ''.join(body_list) - return render_template('md_file.html', footer=footer, body=body, title=title, header_links=hl, go_up=go_up) + hl = header_links_update(links_dict, 0) + topic = 'RSS Feed Links' + lines_list = [] + title = 'RSS Feeds' + info = get_svg(script_directory, 'info') + online = get_svg(script_directory, 'online') + offline = get_svg(script_directory, 'offline') + contact = f'

Send me a message if you want yours added: {news_email}

' + body_list = [] + links, w, on, off = external_site_status_infos(feed_url, online, offline, 'all', True, days) + body_list.append(f'''

All Alive Feeds | {str(on)}/{str(on + off)} seen recently [JSON]

Seen in last {str(days)} days (all sites){w}
''') + for item in cat_dict: + links, w, on, off = external_site_status_infos(feed_url, online, offline, item, True, days) + heading = f'

{cat_dict[item]}' + body_list.append(f'''{heading}{links}
Seen in the last {str(days)} days{w}
''') + body = ''.join(body_list) + return render_template('md_file.html', footer=footer, body=body, title=title, header_links=hl, go_up=go_up) @app.route('/about', methods = ['GET']) def about(): - hl = header_links_update(links_dict, 0) - file = os.path.join(script_directory, 'md_files/newsbot/about.md') - html_file = 'md_file.html' - title = 'About' - try: - with open(file, 'r') as f: - tempMd= f.read() - body = f'
{markdown.markdown(tempMd)}
' - except (FileNotFoundError) as e: - body = 'ERROR - no content found for this!' - return render_template(html_file, footer=footer, body=body, title=title, header_links=hl, go_up=go_up) + hl = header_links_update(links_dict, 0) + file = os.path.join(script_directory, 'md_files/newsbot/about.md') + html_file = 'md_file.html' + title = 'About' + try: + with open(file, 'r') as f: + tempMd= f.read() + body = f'
{markdown.markdown(tempMd)}
' + except (FileNotFoundError) as e: + body = 'ERROR - no content found for this!' + return render_template(html_file, footer=footer, body=body, title=title, header_links=hl, go_up=go_up) @app.route('/tos', methods = ['GET']) def tos(): - hl = header_links_update(links_dict, 0) - html_file = 'md_file.html' - title = 'TOS' - file = os.path.join(script_directory, 'md_files/newsbot/tos.md') - html_file = 'md_file.html' - title = 'TOS' - try: - with open(file, 'r') as f: - tempMd= f.read() - body = f'
{markdown.markdown(tempMd)}
' - except (FileNotFoundError) as e: - body = 'ERROR - no content found for this!' - return render_template(html_file, footer=footer, body=body, title=title, header_links=hl, go_up=go_up) + hl = header_links_update(links_dict, 0) + html_file = 'md_file.html' + title = 'TOS' + file = os.path.join(script_directory, 'md_files/newsbot/tos.md') + html_file = 'md_file.html' + title = 'TOS' + try: + with open(file, 'r') as f: + tempMd= f.read() + body = f'
{markdown.markdown(tempMd)}
' + except (FileNotFoundError) as e: + body = 'ERROR - no content found for this!' + return render_template(html_file, footer=footer, body=body, title=title, header_links=hl, go_up=go_up) @app.route('/changelog', methods = ['GET']) def changelog(): - hl = header_links_update(links_dict, 0) - lines_list = [] - title = 'Changelog' - changelog_txt = 'changelognewsbot.txt' - if os.path.isfile(changelog_txt): - with open(changelog_txt, 'r') as file: - for line_number, line in enumerate(file, start=1): - rm_line_break = line.replace('\n', '') - div = f'
{rm_line_break}
' - lines_list.append(div) - pre = ['
', '
'] - body = f"{pre[0]}{''.join(lines_list)}{pre[1]}" - return render_template('md_file.html', footer=footer, body=body, title=title, header_links=hl, go_up=go_up) + hl = header_links_update(links_dict, 0) + lines_list = [] + title = 'Changelog' + changelog_txt = 'changelognewsbot.txt' + if os.path.isfile(changelog_txt): + with open(changelog_txt, 'r') as file: + for line_number, line in enumerate(file, start=1): + rm_line_break = line.replace('\n', '') + div = f'
{rm_line_break}
' + lines_list.append(div) + pre = ['
', '
'] + body = f"{pre[0]}{''.join(lines_list)}{pre[1]}" + return render_template('md_file.html', footer=footer, body=body, title=title, header_links=hl, go_up=go_up) @app.route('/feed', methods = ['GET']) def rss_feed_all(): - return send_file('rss_all.xml', as_attachment=True) + return send_file('rss_all.xml', as_attachment=True) @app.route('/feed/', methods = ['GET']) def rss_feeds(input_string): - sanitized = sanitize_input(input_string) - rss_list = [] - for key in cat_dict: - rss_list.append(key) - if len(sanitized) > 24: - abort(404) - if sanitized in rss_list: - rss_feed = f'rss_{sanitized}.xml' - return send_file(rss_feed, as_attachment=True) + sanitized = sanitize_input(input_string) + rss_list = [] + for key in cat_dict: + rss_list.append(key) + if len(sanitized) > 24: + abort(404) + if sanitized in rss_list: + rss_feed = f'rss_{sanitized}.xml' + return send_file(rss_feed, as_attachment=True) @app.route('/json', methods = ['GET']) def json(): - return feed_url + return feed_url @app.route('/ping', methods = ['GET']) def ping(): - return "PONG" + return "PONG" @app.route('/robots.txt', methods = ['GET']) def robots(): - return send_file('robots.txt', as_attachment=True) + return send_file('robots.txt', as_attachment=True) @app.route('/', methods = ['GET']) def kill(input_string): - abort(404) + abort(404) ############ #IRC bot ############ class Color(): - a = '\x03' - b = ',01' - white = f'{a}0{b}' - black = f'{a}1{b}' - blue = f'{a}2{b}' - green = f'{a}3{b}' - light_red = f'{a}4{b}' - brown = f'{a}5{b}' - purple = f'{a}6{b}' - orange = f'{a}7{b}' - yellow = f'{a}8{b}' - light_green = f'{a}9{b}' - cyan = f'{a}10{b}' - light_cyan = f'{a}11{b}' - light_blue = f'{a}12{b}' - pink = f'{a}13{b}' - grey = f'{a}14{b}' - light_grey = f'{a}15{b}' - normal = '\x03' + a = '\x03' + b = ',01' + white = f'{a}0{b}' + black = f'{a}1{b}' + blue = f'{a}2{b}' + green = f'{a}3{b}' + light_red = f'{a}4{b}' + brown = f'{a}5{b}' + purple = f'{a}6{b}' + orange = f'{a}7{b}' + yellow = f'{a}8{b}' + light_green = f'{a}9{b}' + cyan = f'{a}10{b}' + light_cyan = f'{a}11{b}' + light_blue = f'{a}12{b}' + pink = f'{a}13{b}' + grey = f'{a}14{b}' + light_grey = f'{a}15{b}' + normal = '\x03' class Irc_bot: - def __init__(self, username, password, hostname, port, channel, primary, auth_users, http_tunnel, bot_send): - def irc_connect(username, password, hostname, port): - network = hostname.encode(encoding='UTF-8',errors='strict') - irc = socket.socket ( socket.AF_INET, socket.SOCK_STREAM ) - irc.connect ( ( network, port ) ) - return irc - def irc_command(command, self): - x = f'{command}\r\n' - y = x.encode(encoding='UTF-8',errors='strict') - try: - self.irc.send (y) - self.reconnect_error, self.reconnect_time = False, 5 - # self.reconnect_error = False - except Exception as e: - if e.errno == errno.EPIPE or e.errno == errno.ECONNRESET: - # self.reconnect_error = True - print('irc_command error') - def irc_bot_init(self): - USR = f"USER {username} {username} {username} :{username}\r\n" - NICK = (bytes(f"NICK {username}\r\n", "UTF-8")) - USER = (bytes(f"USER {username} * * :{username}\r\n", 'UTF-8')) - PASS = (bytes(f'PRIVMSG NickServ IDENTIFY {password}\r\n', "UTF-8")) - QUIT = (bytes(f'QUIT\r\n', "UTF-8")) - JOI = f'JOIN {channel}\r\n' - JOIN = JOI.encode(encoding='UTF-8',errors='strict') - try: - print (self.irc.recv ( 4096 )) - self.reconnect_error, self.reconnect_time = False, 5 - except Exception as e: - if e.errno == errno.EPIPE or e.errno == errno.ECONNRESET: - print('receive error') - self.reconnect_error = True - self.irc = irc_connect(self.username, self.password, self.hostname, self.port) - try: - time.sleep(.5) - self.irc.send (NICK) - time.sleep(.5) - self.irc.send (USER) - time.sleep(.5) - self.reconnect_error, self.reconnect_time = False, 5 - except Exception as e: - if e.errno == errno.EPIPE or e.errno == errno.ECONNRESET: - self.reconnect_error = True - print('ident error') - else: - print('No errors') + def __init__(self, username, password, hostname, port, channel, primary, auth_users, http_tunnel, bot_send): + def irc_connect(username, password, hostname, port): + network = hostname.encode(encoding='UTF-8',errors='strict') + irc = socket.socket ( socket.AF_INET, socket.SOCK_STREAM ) + irc.connect ( ( network, port ) ) + return irc + def irc_command(command, self): + x = f'{command}\r\n' + y = x.encode(encoding='UTF-8',errors='strict') + try: + self.irc.send (y) + self.reconnect_error, self.reconnect_time = False, 5 + # self.reconnect_error = False + except Exception as e: + if e.errno == errno.EPIPE or e.errno == errno.ECONNRESET: + # self.reconnect_error = True + print('irc_command error') + def irc_bot_init(self): + USR = f"USER {username} {username} {username} :{username}\r\n" + NICK = (bytes(f"NICK {username}\r\n", "UTF-8")) + USER = (bytes(f"USER {username} * * :{username}\r\n", 'UTF-8')) + PASS = (bytes(f'PRIVMSG NickServ IDENTIFY {password}\r\n', "UTF-8")) + QUIT = (bytes(f'QUIT\r\n', "UTF-8")) + JOI = f'JOIN {channel}\r\n' + JOIN = JOI.encode(encoding='UTF-8',errors='strict') + try: + print (self.irc.recv ( 4096 )) + self.reconnect_error, self.reconnect_time = False, 5 + except Exception as e: + if e.errno == errno.EPIPE or e.errno == errno.ECONNRESET: + print('receive error') + self.reconnect_error = True + self.irc = irc_connect(self.username, self.password, self.hostname, self.port) + try: + time.sleep(.5) + self.irc.send (NICK) + time.sleep(.5) + self.irc.send (USER) + time.sleep(.5) + self.reconnect_error, self.reconnect_time = False, 5 + except Exception as e: + if e.errno == errno.EPIPE or e.errno == errno.ECONNRESET: + self.reconnect_error = True + print('ident error') + else: + print('No errors') - def irc_setting_update(setting, number, bol, string, floats, initilize): - with app.app_context(): - exists = Settings.query.filter_by(setting=setting).first() - if not exists: - setting = Settings(setting=setting, number=number, bol=bol, string=string, floats=floats) - db.session.add(setting) - db.session.commit() - return number, bol, string, floats - else: - setting = Settings.query.filter_by(setting=setting).first() - if initilize == True: - number = setting.number - bol = setting.bol - string = setting.string - floats = setting.floats - return number, bol, string, floats - else: - setting.number = number - setting.bol = bol - setting.string = string - setting.floats = floats - db.session.commit() - def string_to_list(string): - string_list = string.split(', ') - if len(string_list) == 1: - string_list = string.split(',') - if len(string_list) == 1: - string_list = string.split(' ') - return string_list - self.http_tunnel = http_tunnel - self.auth_users = auth_users - self.msg_l = [] - self.reconnect = 320 - self.new_user_greeting = irc_setting_update('new_user_greeting', 300, False, '', 0, True)[0] - self.new_user_time = irc_setting_update('new_user_greeting', 60, False, '', 0, True)[0] - self.throttle = irc_setting_update('throttle', 0, False, '', 0.25, True)[3] - self.channel_join = string_to_list(irc_setting_update('channel', 0, False, channel, 0, True)[2]) - self.max_posts_per_pull = irc_setting_update('max_posts_per_pull', 10, False, '', 0, True)[0] - self.hostname = hostname - self.port = port - # self.http_port = http_tunnel - self.password = password - self.username = username - self.reconnect_time = 5 - self.first_run = True - self.reconnect_error = False - self.ping_timeout = 320 - self.info_link = 'http://simp.i2p/simpnews' - self.site_link = 'http://i2pnews.simp.i2p' - self.rss_feeds = f"{script_directory}/rsslist.txt" - self.rss_feed_update = irc_setting_update('rss_feed_update', 600, False, '', 0, True)[0] - self.feed_dict = {} - self.new_posts = 0 - self.feed_count = 0 - self.channel_send =['#torrents', '#torrent'] - self.bot_send = [bot_send] - self.color_dict = { - 'blog': Color.pink, - 'developer': Color.light_blue, - 'news': Color.orange, - 'forum': Color.light_red, - 'torrents': Color.light_green - } - def get_feed_list(self): - file_exists = os.path.exists(self.rss_feeds) - if not file_exists: - # is_logged = False - print('RSS FEED FILE NOT FOUND') - else: - print('Loading rss feeds...') - rss_list = [] - file_object_r = open(self.rss_feeds, 'r') - read_file_r = file_object_r.read() - rss_list = read_file_r.splitlines(True) - file_object_r.close() - feed_count = 0 - line_count = 0 - categories = [] - for item in rss_list: - line_count += 1 - l = item.split(' ') - url = l[0] - if line_count != len(rss_list): - category = l[1][:-1] - else: - category = l[1] - if url not in feed_url: - if category in self.color_dict: - # feed_url[url] = category - feed_url[url] = { - 'category': category, - 'description': '', - 'alive': False, - } - feed_count += 1 - else: - print(f'''Feed {url} non accepted category {category} on line {str(line_count)}''') - else: - print(f'Feed {url} already added: line {str(line_count)}') - print(f'Feeds loaded: {str(feed_count)}') - - get_feed_list(self) - - for item in feed_url: - self.feed_dict[item] = "" + def irc_setting_update(setting, number, bol, string, floats, initilize): + with app.app_context(): + exists = Settings.query.filter_by(setting=setting).first() + if not exists: + setting = Settings(setting=setting, number=number, bol=bol, string=string, floats=floats) + db.session.add(setting) + db.session.commit() + return number, bol, string, floats + else: + setting = Settings.query.filter_by(setting=setting).first() + if initilize == True: + number = setting.number + bol = setting.bol + string = setting.string + floats = setting.floats + return number, bol, string, floats + else: + setting.number = number + setting.bol = bol + setting.string = string + setting.floats = floats + db.session.commit() + def string_to_list(string): + string_list = string.split(', ') + if len(string_list) == 1: + string_list = string.split(',') + if len(string_list) == 1: + string_list = string.split(' ') + return string_list + self.http_tunnel = http_tunnel + self.auth_users = auth_users + self.msg_l = [] + self.reconnect = 320 + self.new_user_greeting = irc_setting_update('new_user_greeting', 300, False, '', 0, True)[0] + self.new_user_time = irc_setting_update('new_user_greeting', 60, False, '', 0, True)[0] + self.throttle = irc_setting_update('throttle', 0, False, '', 0.25, True)[3] + self.channel_join = string_to_list(irc_setting_update('channel', 0, False, channel, 0, True)[2]) + self.max_posts_per_pull = irc_setting_update('max_posts_per_pull', 10, False, '', 0, True)[0] + self.hostname = hostname + self.port = port + # self.http_port = http_tunnel + self.password = password + self.username = username + self.reconnect_time = 5 + self.first_run = True + self.reconnect_error = False + self.ping_timeout = 320 + self.info_link = 'http://simp.i2p/simpnews' + self.site_link = 'http://i2pnews.simp.i2p' + self.rss_feeds = f"{script_directory}/rsslist.txt" + self.rss_feed_update = irc_setting_update('rss_feed_update', 600, False, '', 0, True)[0] + self.feed_dict = {} + self.new_posts = 0 + self.feed_count = 0 + self.channel_send = ['#torrents', '#torrent'] + self.bot_send = [bot_send] + self.color_dict = { + 'blog': Color.pink, + 'developer': Color.light_blue, + 'news': Color.orange, + 'forum': Color.light_red, + 'torrents': Color.light_green + } + def get_feed_list(self): + file_exists = os.path.exists(self.rss_feeds) + if not file_exists: + # is_logged = False + print('RSS FEED FILE NOT FOUND') + else: + print('Loading rss feeds...') + rss_list = [] + file_object_r = open(self.rss_feeds, 'r') + read_file_r = file_object_r.read() + rss_list = read_file_r.splitlines(True) + file_object_r.close() + feed_count = 0 + line_count = 0 + categories = [] + for item in rss_list: + line_count += 1 + l = item.split(' ') + url = l[0] + if line_count != len(rss_list): + category = l[1][:-1] + else: + category = l[1] + if url not in feed_url: + if category in self.color_dict: + # feed_url[url] = category + feed_url[url] = { + 'category': category, + 'description': '', + 'alive': False, + } + feed_count += 1 + else: + print(f'''Feed {url} non accepted category {category} on line {str(line_count)}''') + else: + print(f'Feed {url} already added: line {str(line_count)}') + print(f'Feeds loaded: {str(feed_count)}') + + get_feed_list(self) + + for item in feed_url: + self.feed_dict[item] = "" - for item in feed_url: - self.feed_dict[item] = { - 'title': [], - 'link': [], - 'author': [], - 'published': [], - 'description': [], - 'posted': [], - 'latest': '', - 'first_run': True - } - self.feeds_full = {} - self.logger_path = f"{script_directory}/static/rssfeed" - self.logger_mem = {} - self.logger_max = 100 + for item in feed_url: + self.feed_dict[item] = { + 'title': [], + 'link': [], + 'author': [], + 'published': [], + 'description': [], + 'posted': [], + 'latest': '', + 'first_run': True + } + self.feeds_full = {} + self.logger_path = f"{script_directory}/static/rssfeed" + self.logger_mem = {} + self.logger_max = 100 - def save_feed_file(self, byuser, message, script_directory, topic): - logger_file = f"{self.logger_path}/{topic}.txt" - path_exists = os.path.exists(self.logger_path) - file_exists = os.path.exists(logger_file) - if not path_exists: - os.makedirs(self.logger_path) - timestamp_x = "{:%Y-%m-%d %H:%M:%S}".format(datetime.now()) - timestamp_str = str(timestamp_x) - new_line = f'{byuser} {timestamp_str} {message}\n' - if not file_exists: - file_object = open(logger_file, 'a') - file_object.write(new_line) - file_object.close() - else: - file_list = [] - file_object_r = open(logger_file, 'r') - read_file_r = file_object_r.read() - file_list = read_file_r.splitlines(True) - file_list.append(new_line) - file_object_r.close() - # print(str(len(file_list))) - file_object = open(logger_file, 'w') - if len(file_list) > self.logger_max: - file_list = file_list[-100:] - file_object.writelines(file_list) - # print(f'Lines in file: {len(file_list)}') - file_object.close() - def send_irc_msg(self, msg, irc, channel): - split_i = 420 - if len(msg) > split_i: - messages = math.ceil(len(msg) / split_i) - print(messages) - x = 0 - y = split_i - for i in range(0, messages): - if i == messages: - y = len(msg) - # send_it(self, msg[x:y], irc, channel) - self.msg_l.append([msg[x:y], channel]) - x += split_i - y += split_i - else: - self.msg_l.append([msg, channel]) - async def get_feed( - session: aiohttp.ClientSession, - color: str, - proxy_url, - self, - **kwargs - ) -> dict: - url = f"{color}" - print(f"[Requesting] {url}") - start_time = time.time() - resp = await session.request('GET', url=url, proxy=proxy_url, **kwargs) - end_time = time.time() - html = await resp.text() - response_time_ms = (end_time - start_time) * 1000 - try: - if resp.status == 200 or resp.status == 202 or resp.status == 501 or resp.status == 429: - message_x = (f"[green1]Ping to {url} successful. [reset]Response time: {response_time_ms:.2f} ms") - timestamp_x = "{:%Y-%m-%d %H:%M:%S.%f}".format(datetime.now()) - timestamp_update = str(timestamp_x) - ping = (round(response_time_ms, 2)) - online = "Online" - feed_url[url]['alive'] = True - else: - message_x = (f"[red1]Failed to ping {url}. Status code: {response.status_code}[reset]") - timestamp_update = "0" - ping = 0 - online = "Offline" - except Exception as e: - message_x = (f"[red1]Failed to ping {url}. This may be a problem with i2p router or proxy setting here.[reset]") - timestamp_update = '0' - ping = 0 - online = "Offline" - with app.app_context(): - exists = Sites.query.filter_by(site_id=url).first() - if not exists: - site_new = Sites(site_id=url, online=online, last_seen=timestamp_update, ping=(round(ping, 2))) - db.session.add(site_new) - db.session.commit() - else: - site = Sites.query.filter_by(site_id=url).first() - site.online = online - if ping != 0: - site.last_seen = timestamp_update - site.ping = (round(ping, 2)) - db.session.commit() - try: - feed = feedparser.parse(html) - if feed.entries: - self.feed_count += 1 - latest_article = feed.entries[0] - title = latest_article.title - link = latest_article.link - # print(f"[Processing] TITLE {title} | feed_dict[latest] {(self.feed_dict[url])['latest']} | {(self.feed_dict[url])['first_run']}") - if title != (self.feed_dict[url])['latest'] and (self.feed_dict[url])['first_run'] == False: - for i in range(0, len(feed.entries)): - a = feed.entries[i] - if a.title not in (self.feed_dict[url])['title']: - (self.feed_dict[url])['title'].append(a.title) - if a.link[:4].lower() != 'http': - post_url = f'{url}{a.link}' - else: - post_url = a.link - (self.feed_dict[url])['link'].append(post_url) - try: - (self.feed_dict[url])['description'].append(a.description) - except Exception as e: - (self.feed_dict[url])['description'].append('') - (self.feed_dict[url])['posted'].append(False) - else: - pass - (self.feed_dict[url])['latest'] = (title) - print(f'[{str(self.feed_count)}/{str(len(self.feed_dict))}] rss feed updated.') - msg = [] - entries = len((self.feed_dict[url])['title']) - irc_pulls = entries - self.max_posts_per_pull - for i in range(0, entries): - if (self.feed_dict[url])['posted'][i] == False: - msg_title = (self.feed_dict[url])['title'][i] - msg_description = (self.feed_dict[url])['description'][i] - if len(msg_description) > 50: - msg_description = f'{msg_description[:50]}...' - msg_url = (self.feed_dict[url])['link'][i] - col = self.color_dict[feed_url[url]['category']] - shorten = get_short_url(url) - if get_host(msg_url).casefold() == '127.0.0.1': - url_q = msg_url.split(shorten)[1] - msg_url = f'http://{shorten}{url_q}' - msg_s = (f"{col}[{shorten}]{Color.normal} {msg_title} - {msg_url}") - # msg_f = f'''{msg_title} - {msg_description} ::{msg_url}''' - msg_f = f'''::{msg_url} @@@{msg_title}''' - (self.feed_dict[url])['posted'][i] = True - self.new_posts += 1 - if i >= irc_pulls: - for item in self.channel_join: - send_irc_msg(self, msg_s, self.irc, item) - save_feed_file(self, f'''{shorten}:{feed_url[url]['category']}''', msg_f, script_directory, feed_url[url]['category']) - save_feed_file(self, f'''{shorten}:{feed_url[url]['category']}''', msg_f, script_directory, 'all') - # if feed_url[url]['category'] == 'torrents': + def save_feed_file(self, byuser, message, script_directory, topic): + logger_file = f"{self.logger_path}/{topic}.txt" + path_exists = os.path.exists(self.logger_path) + file_exists = os.path.exists(logger_file) + if not path_exists: + os.makedirs(self.logger_path) + timestamp_x = "{:%Y-%m-%d %H:%M:%S}".format(datetime.now()) + timestamp_str = str(timestamp_x) + new_line = f'{byuser} {timestamp_str} {message}\n' + if not file_exists: + file_object = open(logger_file, 'a') + file_object.write(new_line) + file_object.close() + else: + file_list = [] + file_object_r = open(logger_file, 'r') + read_file_r = file_object_r.read() + file_list = read_file_r.splitlines(True) + file_list.append(new_line) + file_object_r.close() + # print(str(len(file_list))) + file_object = open(logger_file, 'w') + if len(file_list) > self.logger_max: + file_list = file_list[-100:] + file_object.writelines(file_list) + # print(f'Lines in file: {len(file_list)}') + file_object.close() + def send_irc_msg(self, msg, irc, channel): + split_i = 420 + if len(msg) > split_i: + messages = math.ceil(len(msg) / split_i) + print(messages) + x = 0 + y = split_i + for i in range(0, messages): + if i == messages: + y = len(msg) + # send_it(self, msg[x:y], irc, channel) + self.msg_l.append([msg[x:y], channel]) + x += split_i + y += split_i + else: + self.msg_l.append([msg, channel]) + + def get_title(shorten, latest_article): + gits = [ + 'git.simp.i2p', + 'git.community.i2p', + 'git.idk.i2p', + ] + if shorten in gits: + try: + title = (latest_article.content[0]['value'].split('\n')[1]) + except Exception as e: + title = latest_article.title + elif 'title' in latest_article: + title = latest_article.title + else: + if 'terminus_answer' in latest_article: + post_number_list = latest_article.terminus_answer.split(' ') + post_number = post_number_list[len(post_number_list)-1] + terminus_answer = f' reply to #{post_number} ' + else: + post_number = '' + terminus_answer = 'new post' + if 'terminus_timestamp' in latest_article: + terminus_timestamp = f' at {latest_article.terminus_timestamp} ' + else: + terminus_timestamp = '' + if 'terminus_author' in latest_article: + terminus_author = f' by {latest_article.terminus_author} ' + else: + terminus_author = ' anon ' + def strip_bbcode(msg, post_number): + max_chars = 200 + s = [ + ']', '[b', '[i', '[li', '[s', '[sp', '[h', '[u', '[url', '[wiki', '[t', '[find', '"', '\n', '>', '>>' + ] + if len(post_number) != 0: + s.append(post_number) + for i in s: + msg = msg.replace(i, '') + msg_len = len(msg) + if msg_len > max_chars: + msg = f'{msg[:max_chars]}...' + return msg + description = strip_bbcode(latest_article.description, post_number) + title = f'/s {latest_article.terminus_sub}{terminus_timestamp}{terminus_answer}{terminus_author} {description}' + return title + + async def get_feed( + session: aiohttp.ClientSession, + color: str, + proxy_url, + self, + **kwargs + ) -> dict: + url = f"{color}" + print(f"[Requesting] {url}") + start_time = time.time() + resp = await session.request('GET', url=url, proxy=proxy_url, **kwargs) + end_time = time.time() + html = await resp.text() + response_time_ms = (end_time - start_time) * 1000 + try: + if resp.status == 200 or resp.status == 202 or resp.status == 501 or resp.status == 429: + message_x = (f"[green1]Ping to {url} successful. [reset]Response time: {response_time_ms:.2f} ms") + timestamp_x = "{:%Y-%m-%d %H:%M:%S.%f}".format(datetime.now()) + timestamp_update = str(timestamp_x) + ping = (round(response_time_ms, 2)) + online = "Online" + feed_url[url]['alive'] = True + else: + message_x = (f"[red1]Failed to ping {url}. Status code: {response.status_code}[reset]") + timestamp_update = "0" + ping = 0 + online = "Offline" + except Exception as e: + message_x = (f"[red1]Failed to ping {url}. This may be a problem with i2p router or proxy setting here.[reset]") + timestamp_update = '0' + ping = 0 + online = "Offline" + with app.app_context(): + exists = Sites.query.filter_by(site_id=url).first() + if not exists: + site_new = Sites(site_id=url, online=online, last_seen=timestamp_update, ping=(round(ping, 2))) + db.session.add(site_new) + db.session.commit() + else: + site = Sites.query.filter_by(site_id=url).first() + site.online = online + if ping != 0: + site.last_seen = timestamp_update + site.ping = (round(ping, 2)) + db.session.commit() + try: + feed = feedparser.parse(html) + if feed.entries: + self.feed_count += 1 + shorten = get_short_url(url) + latest_article = feed.entries[0] + # title = latest_article.title + title = get_title(shorten, latest_article) + # link = latest_article.link + # print(f"[Processing] TITLE {title} | feed_dict[latest] {(self.feed_dict[url])['latest']} | {(self.feed_dict[url])['first_run']}") + if title != (self.feed_dict[url])['latest'] and (self.feed_dict[url])['first_run'] == False: + for i in range(0, len(feed.entries)): + a = feed.entries[i] + a_title = get_title(shorten, a) + # if a.title not in (self.feed_dict[url])['title']: + if a_title not in (self.feed_dict[url])['title']: + (self.feed_dict[url])['title'].append(a_title) + if shorten != 'hackernews.i2p': + if a.link[:4].lower() != 'http': + post_url = f'{url}{a.link}' + else: + post_url = a.link + else: + post_url = a.comments.replace('https://news.ycombinator.com', 'http://hackernews.i2p') + (self.feed_dict[url])['link'].append(post_url) + try: + (self.feed_dict[url])['description'].append(a.description) + except Exception as e: + (self.feed_dict[url])['description'].append('') + (self.feed_dict[url])['posted'].append(False) + else: + pass + (self.feed_dict[url])['latest'] = (title) + print(f'[{str(self.feed_count)}/{str(len(self.feed_dict))}] rss feed updated.') + msg = [] + entries = len((self.feed_dict[url])['title']) + irc_pulls = entries - self.max_posts_per_pull + switch_urls = [ + 'iranfreedom.org', + 'paltepuk.neocities.org', + '127.0.0.1', + '127.0.0.1:7672', + 'localhost', + 'localhost:7672', + ] + forbidden = ['#i2p-news-clean'] + for i in range(0, entries): + # for i in range(entries, 0, -1): + if (self.feed_dict[url])['posted'][i] == False: + msg_title = (self.feed_dict[url])['title'][i] + msg_description = (self.feed_dict[url])['description'][i] + if len(msg_description) > 50: + msg_description = f'{msg_description[:50]}...' + msg_url = (self.feed_dict[url])['link'][i] + col = self.color_dict[feed_url[url]['category']] + the_host = get_host(msg_url) + # if the_host in switch_urls: + # # url_q = msg_url.split(shorten)[1] + # url_q = msg_url.replace(the_host, shorten) + # msg_url = f'http://{url_q}' + if the_host in switch_urls: + url_q = msg_url.replace(the_host, shorten) + if len(url_q) > 7: + url_q = url_q.replace('https://', 'http://') + if url_q[:7] != 'http://': + url_q = f'http://{url_q}' + msg_url = url_q + + msg_s = (f"{col}[{shorten}]{Color.normal} {msg_title} - {msg_url}") + # msg_f = f'''{msg_title} - {msg_description} ::{msg_url}''' + msg_f = f'''::{msg_url} @@@{msg_title}''' + (self.feed_dict[url])['posted'][i] = True + self.new_posts += 1 + if i >= irc_pulls: + for item in self.channel_join: + if item not in forbidden: + send_irc_msg(self, msg_s, self.irc, item) + save_feed_file(self, f'''{shorten}:{feed_url[url]['category']}''', msg_f, script_directory, feed_url[url]['category']) + save_feed_file(self, f'''{shorten}:{feed_url[url]['category']}''', msg_f, script_directory, 'all') + # if feed_url[url]['category'] == 'torrents': + if shorten.lower() == 'tracker2.postman.i2p' or is_url_ours(url) == True or feed_url[url]['category'].lower() == 'torrents': + for c in self.channel_send: + payload = { + 'sender': get_short_url(url), + 'send_to': c, + 'title': msg_title, + 'url': msg_url, + } + send_message(self.bot_send, payload) + else: + for item in forbidden: + send_irc_msg(self, msg_s, self.irc, item) + if shorten.lower() == 'gatheryourparty.i2p': + payload = { + 'sender': get_short_url(url), + 'send_to': '#gatheryourparty', + 'title': msg_title, + 'url': msg_url, + } + send_message(self.bot_send, payload) + generate_rss_feed() - if shorten.lower() == 'tracker2.postman.i2p' or is_url_ours(url) == True or feed_url[url]['category'].lower() == 'torrents': - for c in self.channel_send: - payload = { - 'sender': get_short_url(url), - 'send_to': c, - 'title': msg_title, - 'url': msg_url, - } - send_message(self.bot_send, payload) - generate_rss_feed() + + elif (self.feed_dict[url])['first_run'] == True: + print(f'[{str(self.feed_count)}/{str(len(self.feed_dict))}] grabbing feeds for first run.') + (self.feed_dict[url])['latest'] = title + # (self.feed_dict[url])['title'].append(title) + # (self.feed_dict[url])['link'].append(link) + # (self.feed_dict[url])['description'].append(a.description) + # (self.feed_dict[url])['posted'].append(True) + (self.feed_dict[url])['first_run'] = False + for i in range(0, len(feed.entries)): + a = feed.entries[i] + a_title = get_title(shorten, a) + if a_title not in (self.feed_dict[url])['title']: + (self.feed_dict[url])['title'].append(a_title) + (self.feed_dict[url])['link'].append(a.link) + try: + (self.feed_dict[url])['description'].append(a.description) + except Exception as e: + (self.feed_dict[url])['description'].append('') + (self.feed_dict[url])['posted'].append(True) - - elif (self.feed_dict[url])['first_run'] == True: - print(f'[{str(self.feed_count)}/{str(len(self.feed_dict))}] grabbing feeds for first run.') - (self.feed_dict[url])['latest'] = title - # (self.feed_dict[url])['title'].append(title) - # (self.feed_dict[url])['link'].append(link) - # (self.feed_dict[url])['description'].append(a.description) - # (self.feed_dict[url])['posted'].append(True) - (self.feed_dict[url])['first_run'] = False - for i in range(0, len(feed.entries)): - a = feed.entries[i] - if a.title not in (self.feed_dict[url])['title']: - (self.feed_dict[url])['title'].append(a.title) - (self.feed_dict[url])['link'].append(a.link) - try: - (self.feed_dict[url])['description'].append(a.description) - except Exception as e: - (self.feed_dict[url])['description'].append('') - (self.feed_dict[url])['posted'].append(True) - - else: - print(f'[{str(self.feed_count)}/{str(len(self.feed_dict))}] FAILED: {url} ') - except Exception as e: - print(f'[{str(self.feed_count)}/{str(len(self.feed_dict))}] RSS feed error {e} on {get_short_url(url)}') - - async def gather_feeds(self, feeds, proxy_url, **kwargs): - async with aiohttp.ClientSession() as session: - tasks = [] - for c in feeds: - tasks.append(get_feed(session=session, color=c, proxy_url=proxy_url, self=self, **kwargs)) - htmls = await asyncio.gather(*tasks, return_exceptions=True) - return htmls - def irc_rss_feed_control(exit_event, self): - print(f'Starting RSS feed bot') - proxy_url = f'http://{self.hostname}:{self.http_tunnel}' - feed_list_test = [] - for item in feed_url: - feed_list_test.append(item) - while not exit_event.is_set(): - self.feed_count = 0 - htmls = asyncio.run(gather_feeds(self, feed_list_test, proxy_url)) - if self.first_run == True: - print(f"Finished updating {str(len(self.feed_dict))} feeds.") - self.first_run = False - time.sleep(self.rss_feed_update) - def send_throttle(exit_event, self): - start = True - while not exit_event.is_set(): - time.sleep(self.throttle) - try: - msg = (self.msg_l[0])[0] - channel = (self.msg_l[0])[1] - print(f'ACTUAL MSG: {msg}') - command = f"PRIVMSG {channel}" - MESSAGE = (bytes(f'{command} {msg}\r\n', "UTF-8")) - if start == True: - start = False - self.msg_l.pop(1) - self.msg_l.pop(0) - else: - self.irc.send (MESSAGE) - if len(self.msg_l) > 0: - self.msg_l.pop(0) - - except Exception as e: - pass - def irc_rec(exit_event, self, username, password, hostname, port, channel, http_port, primary, auth_users): - network = hostname - self.hostname = hostname - self.port = port - self.password = password - self.username = username - print('IRC BOT START') - USR = f"USER {username} {username} {username} :{username}\r\n" - NICK = (bytes(f"NICK {username}\r\n", "UTF-8")) - USER = (bytes(f"USER {username} * * :{username}\r\n", 'UTF-8')) - PASS = (bytes(f'PRIVMSG NickServ IDENTIFY {password}\r\n', "UTF-8")) - QUIT = (bytes(f'QUIT\r\n', "UTF-8")) - JOI = f'JOIN {channel}\r\n' - JOIN = JOI.encode(encoding='UTF-8',errors='strict') - irc_bot_init(self) - self.new_users = {} - tr = '$' - self.new_user_message = [ - f"I'm a newsbot :) ", - f"{Color.yellow}{tr}help{Color.normal} for a list of things i can do.", - f"people could be sleeping or afk. stick around a bit :)", - ] - self.greetings = ['hello', 'hi', 'welcome πŸ‘‹', 'greetings', 'hellooooo there', 'good morning, or afternoon, or whatever', '✨salutations✨'] - self.hi = [f"hi i'm {username}", "i'm just a simple newsbot","rss feeds all day"] - self.greetings_end = ['! :)', ' 🀠', ' πŸ₯³', '!!!', ' πŸ‘€', ' 😌', ' 🀩'] - def ping(self, line): - try: - print('PING RECIEVED') - self.irc.send (bytes("PONG %s\r\n" % line[1], "UTF-8")) - self.last_ping = time.time() - except Exception as e: - if e.errno == errno.EPIPE or e.errno == errno.ECONNRESET: - print('PING error') - def where_to_send(line): - print(line) - if line[1] == 'PRIVMSG' and line[2][:1:] != '#': - print('SEND PRIV') - send_to = ((line[0].split('!'))[0])[1:] - print(send_to) - else: - print('SEND TO CHAN') - send_to = line[2] - print(send_to) - return send_to - - # send_it(self, msg, irc, channel) - def check_if_banned(self, line): - user = ((line[0].split('!'))[0])[1:] - if user in self.auth_users: - return False - else: - with app.app_context(): - exists = Irc.query.filter_by(user=user).first() - if exists: - u = Irc.query.filter_by(user=user).first() - banned = u.banned - return banned - else: - return False - def new_user(self, line): - if check_if_banned(self, line) == False: - user_list = [line[4], (line[5])[1:]] - all_users = [] - send_to = where_to_send(line) - - with app.app_context(): - for i in range(5, len(line)): - new_added = [] - user_list.append(line[i]) - user_slice = (line[i])[:1] - - def ampersand(line): - if (line)[:5] == '&': - nick = (line)[5:] - else: - nick = (line)[1:] - return nick - - if user_slice == '@' or user_slice == '~' or user_slice == '%' or user_slice == '&': - admin = True - nick = ampersand(line[i]) - if nick not in self.auth_users: - self.auth_users.append(nick) - new_added.append(nick) - elif (line[i])[1:] in self.auth_users: - admin = True - else: - admin = False - - if user_slice == '@' or user_slice == '~' or user_slice == '%' or user_slice == '+' or user_slice == ':' or user_slice == '&': - user_sliced = ampersand(line[i]) - # user_sliced = (line[i])[1:] - - else: - user_sliced = line[i] - #&kytv - # if line[i] not in user_list - print(f'USER SLICED {user_sliced}') - # db.create_all() - # for item in all_sites: - exists = Irc.query.filter_by(user=user_sliced).first() - if not exists: - timestamp_x = "{:%Y-%m-%d %H:%M:%S.%f}".format(datetime.now()) - timestamp_str = str(timestamp_x) - new_user = Irc(user=user_sliced, first_seen=timestamp_str, admin=admin, banned=False, points=0, welcomed=False, approved=False, tracker_code='', invites=0) - db.session.add(new_user) - db.session.commit() - - print(user_list) - user_list_string = (' ').join(user_list) - if len(new_added) > 0: - authed = f"{Color.yellow}now authorized: {(' ').join(new_added)}{Color.normal}" - send_irc_msg(self, authed, self.irc, send_to) - def mode_registered(self, line): - try: - if line[3] == ':+r': - print('USERNAME REGISTERED!') - state = f"Username already {username} registered. Please choose a different name." - # break - except Exception as e: - print(f"Error: {e}") - def say_hello(self, line): - if check_if_banned(self, line) == False: - send_to = where_to_send(line) - random.choice(self.hi) - msg = [] - c = (random.choice(self.hi)) - msg.append(f'{c}{Color.yellow} {tr}help for commands | {tr}help for info{Color.normal}') - for item in msg: - send_irc_msg(self, item, self.irc, send_to) - def new_user_add(self, line): - if check_if_banned(self, line) == False: - send_to = where_to_send(line) - msg = [] - for key in self.new_users: - self.new_users[key] = (self.new_users[key]) + 1 - def remaining_msg_irc(line, start, spacer, include_reason): - x = '' - n = start+1 - if len(line) > n: - for i in range(n, len(line)): - if i >= len(line) - 1: - end_space = '' - else: - end_space = ' ' - x = f'{x}{line[i]}{end_space}' - if spacer == True: - x = f' {x}' - - y = f"{x}" - else: - y = f' none given.' - return x, y - def register_user(username, newpassword): - irc_command(f"PRIVMSG NickServ register {newpassword} {username}@mail.i2p\r\n", self) - # REG = (bytes(f'PRIVMSG NickServ register {newpassword} {username}@mail.i2p\r\n', "UTF-8")) - # self.irc.send (REG) - def new_user_timer_joined(self, line): - if check_if_banned(self, line) == False: - send_to = where_to_send(line) - msg = [] - - time_date_format = '%Y-%m-%d %H:%M:%S.%f' - joined_named = ((line[0]).split('!')[0])[1:] - with app.app_context(): - exists = Irc.query.filter_by(user=joined_named).first() - if exists: - - u = Irc.query.filter_by(user=joined_named).first() - time_obj = datetime.strptime(u.first_seen, time_date_format) - last_seen_str = time_obj.strftime('%d-%m-%Y') - time_now_obj = datetime.now() - difference = time_now_obj - time_obj - time_difference = timedelta(minutes=self.new_user_time) - if difference < time_difference and u.welcomed == False: - # msg.append(f'new user') - if joined_named not in self.new_users: - self.new_users[joined_named] = 0 - - exit_timer = threading.Event() - thread_timer = threading.Thread(target=new_user_timer, args=(exit_timer, self, send_to, self.irc, u)) - thread_timer.start() - else: - if joined_named in self.new_users: - self.new_users.pop(joined_named) - # msg.append(f'no longer new user: {joined_named}') - else: - msg.append(f'new user') - if joined_named not in self.new_users: - self.new_users[joined_named] = 0 - time_now_obj = datetime.now() - - exit_timer = threading.Event() - thread_timer = threading.Thread(target=new_user_timer, args=(exit_timer, self, send_to, self.irc, joined_named)) - thread_timer.start() + else: + print(f'[{str(self.feed_count)}/{str(len(self.feed_dict))}] FAILED: {url} ') + except Exception as e: + print(f'[{str(self.feed_count)}/{str(len(self.feed_dict))}] RSS feed error {e} on {get_short_url(url)}') - for item in msg: - send_irc_msg(self, item, self.irc, send_to) - def join_chan(self, line): - if check_if_banned(self, line) == False: - # send_to = where_to_send(line) - msg = [] - time_date_format = '%Y-%m-%d %H:%M:%S.%f' - joined_named = ((line[0]).split('!')[0])[1:] - send_to = (line[2])[1:] - with app.app_context(): - exists = Irc.query.filter_by(user=joined_named).first() - if exists: + async def gather_feeds(self, feeds, proxy_url, **kwargs): + async with aiohttp.ClientSession() as session: + tasks = [] + for c in feeds: + tasks.append(get_feed(session=session, color=c, proxy_url=proxy_url, self=self, **kwargs)) + htmls = await asyncio.gather(*tasks, return_exceptions=True) + return htmls + def irc_rss_feed_control(exit_event, self): + print(f'Starting RSS feed bot') + proxy_url = f'http://{self.hostname}:{self.http_tunnel}' + feed_list_test = [] + for item in feed_url: + feed_list_test.append(item) + while not exit_event.is_set(): + self.feed_count = 0 + htmls = asyncio.run(gather_feeds(self, feed_list_test, proxy_url)) + if self.first_run == True: + print(f"Finished updating {str(len(self.feed_dict))} feeds.") + self.first_run = False + time.sleep(self.rss_feed_update) + def send_throttle(exit_event, self): + start = True + while not exit_event.is_set(): + time.sleep(self.throttle) + try: + msg = (self.msg_l[0])[0] + channel = (self.msg_l[0])[1] + print(f'ACTUAL MSG: {msg}') + command = f"PRIVMSG {channel}" + MESSAGE = (bytes(f'{command} {msg}\r\n', "UTF-8")) + if start == True: + start = False + self.msg_l.pop(1) + self.msg_l.pop(0) + else: + self.irc.send (MESSAGE) + if len(self.msg_l) > 0: + self.msg_l.pop(0) - u = Irc.query.filter_by(user=joined_named).first() - time_obj = datetime.strptime(u.first_seen, time_date_format) - last_seen_str = time_obj.strftime('%d-%m-%Y') - time_now_obj = datetime.now() - difference = time_now_obj - time_obj - time_difference = timedelta(minutes=self.new_user_time) - if difference < time_difference: - # msg.append(f'new user') - if joined_named not in self.new_users: - self.new_users[joined_named] = 0 - # u = Newuser(joined_named, time_now_obj, 0) - else: - if joined_named in self.new_users: - self.new_users.pop(joined_named) - # msg.append(f'no longer new user: {joined_named}') - # for i in range(0, len(new_users)): - # if new_users[i] == joined_named: - # new_users.pop(i) - # msg.append(f'no longer new user: {joined_named}') - # msg.append(f'{u.user}, {last_seen_str}, {str(u.admin)}, {str(u.banned)}, {str(u.points)}') - else: - # msg.append(f'new user') - if joined_named not in self.new_users: - self.new_users[joined_named] = 0 - time_now_obj = datetime.now() + except Exception as e: + pass + def irc_rec(exit_event, self, username, password, hostname, port, channel, http_port, primary, auth_users): + network = hostname + self.hostname = hostname + self.port = port + self.password = password + self.username = username + print('IRC BOT START') + USR = f"USER {username} {username} {username} :{username}\r\n" + NICK = (bytes(f"NICK {username}\r\n", "UTF-8")) + USER = (bytes(f"USER {username} * * :{username}\r\n", 'UTF-8')) + PASS = (bytes(f'PRIVMSG NickServ IDENTIFY {password}\r\n', "UTF-8")) + QUIT = (bytes(f'QUIT\r\n', "UTF-8")) + JOI = f'JOIN {channel}\r\n' + JOIN = JOI.encode(encoding='UTF-8',errors='strict') + irc_bot_init(self) + self.new_users = {} + tr = '$' + self.new_user_message = [ + f"I'm a newsbot :) ", + f"{Color.yellow}{tr}help{Color.normal} for a list of things i can do.", + f"people could be sleeping or afk. stick around a bit :)", + ] + self.greetings = ['hello', 'hi', 'welcome πŸ‘‹', 'greetings', 'hellooooo there', 'good morning, or afternoon, or whatever', '✨salutations✨'] + self.hi = [f"hi i'm {username}", "i'm just a simple newsbot","rss feeds all day"] + self.greetings_end = ['! :)', ' 🀠', ' πŸ₯³', '!!!', ' πŸ‘€', ' 😌', ' 🀩'] + def ping(self, line): + try: + print('PING RECIEVED') + self.irc.send (bytes("PONG %s\r\n" % line[1], "UTF-8")) + self.last_ping = time.time() + except Exception as e: + if e.errno == errno.EPIPE or e.errno == errno.ECONNRESET: + print('PING error') + def where_to_send(line): + print(line) + if line[1] == 'PRIVMSG' and line[2][:1:] != '#': + print('SEND PRIV') + send_to = ((line[0].split('!'))[0])[1:] + print(send_to) + else: + print('SEND TO CHAN') + send_to = line[2] + print(send_to) + return send_to - for item in msg: - send_irc_msg(self, item, self.irc, send_to) - - names = f'NAMES {send_to}\r\n'.encode(encoding='UTF-8',errors='strict') - self.irc.send (names) - # send_irc_msg(self, msg, irc, send_to) - def identify_bot(self): - irc_command(f'PRIVMSG NickServ GHOST {self.username} {self.password}', self) - time.sleep(0.25) - irc_command(f'PRIVMSG NickServ IDENTIFY {self.password}', self) - time.sleep(.25) - for item in self.channel_join: - irc_command(f'JOIN {item}', self) - time.sleep(0.25) - irc_command(f'NAMES {item}', self) - time.sleep(0.25) - time.sleep(0.25) - irc_command(f'MODE {self.username} +B', self) - send_irc_msg(self, '', self.irc, 'username') - send_irc_msg(self, '', self.irc, 'username') - def register_bot(self, line): - user = ((line[0].split('!'))[0])[1:] - if line[1] == '451' and len(line) >= 4: - reg = [] - for i in range(4, len(line)): - reg.append(line[i]) - reg_s = ' '.join(reg) - print(reg_s) - register_user(username, password) - try: - if line[6] == "not" and line[7] == 'registered.': - register_user(username, password) - new_nick = True - elif line[3].lower() == ":if" and line[4].lower() == 'you': - identify_bot(self) - elif line[3].lower() == ":this" and line[6].lower() == 'registered.': - identify_bot(self) - elif user.lower() == 'nickserv': - if len(line) >=4: - reg = [] - for i in range(4, len(line)): - reg.append(line[i]) - reg_s = (' '.join(reg)).lower() - else: - reg_s = '' - if line[3].lower() == ':welcome': - identify_bot(self) - elif reg_s == 'is not a registered nickname.': - register_user(username, password) - new_nick = True - except Exception as e: - print(f"Error: {e}") - def admin(sefl, line): - do_command = False - send_to = where_to_send(line) - if ((line[0].split('!'))[0])[1:] in self.auth_users: - msg = [] + # send_it(self, msg, irc, channel) + def check_if_banned(self, line): + user = ((line[0].split('!'))[0])[1:] + if user in self.auth_users: + return False + else: + with app.app_context(): + exists = Irc.query.filter_by(user=user).first() + if exists: + u = Irc.query.filter_by(user=user).first() + banned = u.banned + return banned + else: + return False + def new_user(self, line): + if check_if_banned(self, line) == False: + user_list = [line[4], (line[5])[1:]] + all_users = [] + send_to = where_to_send(line) - try: - admin_user = f"{Color.pink}[admin {((line[0].split('!'))[0])[1:]}]{Color.normal}" - com_msg = f'{Color.yellow}[command]{Color.normal}' - com_err = f'{Color.light_red}[COMMAND ERROR]{Color.normal}' - rs = f'{Color.yellow}[reason]{Color.normal}' - ms = f'{Color.yellow}[msg]{Color.normal}' - - if 'help' in line[4]: - command_list = [ - f'part ', - f'join ', - f'refresh', - f'say ', - f'command ', - f'kill ', - f'check ', - f'ignore / unignore ', - f'{Color.yellow}[info]{Color.normal} accepts commands in a given channel or through pm. optional. command = raw irc command. ignored users are ignored by the bot.' - ] + with app.app_context(): + for i in range(5, len(line)): + new_added = [] + user_list.append(line[i]) + user_slice = (line[i])[:1] + + def ampersand(line): + if (line)[:5] == '&': + nick = (line)[5:] + else: + nick = (line)[1:] + return nick - settings_list = [ - f'rss_feed_update ', - f'max_posts ', - 'main_channel <#channel>', - 'throttle ', - f'{Color.yellow}[info]{Color.normal} command without new gives current value. throttle is (s) between msg sends. main_channel is a list to join on connect, seperated by space or comma "#chan1 #chan2 #chan3' - ] - msg.append(f"{Color.yellow}[admin commands]{Color.normal} {' | '.join(command_list)}") - # msg.append(f"{Color.yellow}[tracker commands]{Color.normal} {' | '.join(tracker_commands)}") - msg.append(f"{Color.yellow}[admin settings]{Color.normal} {' | '.join(settings_list)}") - msg.append(f"{Color.yellow}[Preface all commands with {tr}admin]{Color.normal} ex: {tr}admin throttle 0.5 {Color.yellow}[more info]{Color.normal} {self.info_link}") - elif 'part' in line[4]: - reason, reason_msg = remaining_msg_irc(line, 5, True, True) - do_command = True - msg.append(f"{admin_user} {com_msg} part channel {line[5]} {rs}{reason_msg}") - time.sleep(self.throttle + 2) - command = [f'PRIVMSG MemoServ send {primary} {msg[0]}', f'PART {line[5]}{reason}'] - elif 'join' in line[4]: - do_command = True - msg.append(f"{admin_user} {com_msg} join channel {line[5]}") - msg.append(f'{Color.light_red}joining channel {line[5]} πŸ‘οΈπŸ‘„πŸ‘οΈ{Color.normal}') - command = [f'PRIVMSG MemoServ send {primary} {msg[0]}', f'JOIN {line[5]}'] - elif 'kill' in line[4]: - do_command = True - reason, reason_msg = remaining_msg_irc(line, 4, True, True) - do_command = True - msg.append(f"{admin_user} {com_msg} {Color.light_red}KILL{Color.normal} {rs}{reason_msg}") - msg.append(f'{Color.light_red}disconnecting 😴{Color.normal}') - time.sleep(self.throttle + 2) - command = [f'PRIVMSG MemoServ send {primary} {msg[0]}', f'QUIT {reason}'] - elif 'say' in line[4]: - do_command = True - reason, reason_msg = remaining_msg_irc(line, 5, True, True) - do_command = True - msg.append(f"{admin_user} {com_msg} say to {line[5]} {ms}{reason_msg}") - command = [f'PRIVMSG {line[5]} {reason}'] - - elif 'refresh' in line[4]: - do_command = False - get_feed_list(self) - msg.append(f"{admin_user} {com_msg} refreshing feed list.") - # command = [f'PRIVMSG {line[5]} {reason}'] - elif 'throttle' in line[4]: - reason, reason_msg = remaining_msg_irc(line, 4, False, False) - do_command = False - - if len(line) >= 6: - m = 5 - try: - new_time_f = float(line[5]) - if new_time_f <= m: - msg.append(f"{admin_user} {com_msg} send message throttle set to {line[5]}s") - self.throttle = new_time_f - irc_setting_update('throttle', 0, False, '', new_time_f, False) - else: - msg.append(f"{admin_user} {com_err} too long, {m}s max.") - - except Exception as e: - print(e) - msg.append(f"{admin_user} {com_err} not valid input, takes a float (seconds), 5s max.") - else: - msg.append(f"{admin_user} {Color.yellow}[message throttle]{Color.normal} {str(self.throttle)}s") - - print(str(len(line))) - elif 'feed_update' in line[4]: - reason, reason_msg = remaining_msg_irc(line, 4, False, False) - do_command = False - - if len(line) >= 6: - m = 60 - try: - new_time_f = float(line[5]) - if new_time_f >= m: - msg.append(f"{admin_user} {com_msg} checks all feeds in {line[5]}s") - self.rss_feed_update = new_time_f - irc_setting_update('rss_feed_update', 0, False, '', new_time_f, False) - else: - msg.append(f"{admin_user} {com_err} too short, {m}s min.") - - except Exception as e: - print(e) - msg.append(f"{admin_user} {com_err} not valid input, takes a float (seconds), 60s min.") - else: - msg.append(f"{admin_user} {Color.yellow}[Feed Update]{Color.normal} {str(self.rss_feed_update)}s") - elif 'max_posts' in line[4]: - reason, reason_msg = remaining_msg_irc(line, 4, False, False) - do_command = False - - if len(line) >= 6: - m = 50 - try: - new_setting = int(line[5]) - if new_setting <= m: - msg.append(f"{admin_user} {com_msg} set max post per feed per update at {line[5]}") - self.max_posts_per_pull = new_setting - irc_setting_update('max_posts_per_pull', new_setting, False, '', 0, False) - else: - msg.append(f"{admin_user} {com_err} too many {m} max.") - - except Exception as e: - print(e) - msg.append(f"{admin_user} {com_err} not valid input, takes an int {str(m)} max.") - else: - msg.append(f"{admin_user} {Color.yellow}[Max posts per pull]{Color.normal} {str(self.max_posts_per_pull)}") - print(str(len(line))) - elif 'check' in line[4]: - reason, reason_msg = remaining_msg_irc(line, 4, False, False) - do_command = False - if len(line) >= 6: - try: - nick = line[5] - msg = [] - with app.app_context(): + if user_slice == '@' or user_slice == '~' or user_slice == '%' or user_slice == '&': + admin = True + nick = ampersand(line[i]) + if nick not in self.auth_users: + self.auth_users.append(nick) + new_added.append(nick) + elif (line[i])[1:] in self.auth_users: + admin = True + else: + admin = False - - time_date_format = '%Y-%m-%d %H:%M:%S.%f' - with app.app_context(): - exists = Irc.query.filter_by(user=nick).first() - # exists = Irc.query.filter_by((func.lower(user) == nick.lower())).first() - if not exists: - msg.append(f"{admin_user} {com_err} i don't know user {nick}") - else: - # func.lower(countries.name) == name.lower(), - # func.lower(countries.capital) == capital.lower() - u = Irc.query.filter_by(user=nick).first() - time_obj = datetime.strptime(u.first_seen, time_date_format) - last_seen_str = time_obj.strftime('%d-%m-%Y') - time_now_obj = datetime.now() - difference = time_now_obj - time_obj - time_difference = timedelta(minutes=30) - if difference < time_difference: - new_user = True - else: - new_user = False - # user, first_seen, admin, banned, new, points - user_info = [ - f'{admin_user} {com_msg} user info', - f'{Color.yellow}[user]{Color.normal} {u.user}', - f'{Color.yellow}[first seen]{Color.normal} {last_seen_str}', - f'{Color.yellow}[admin]{Color.normal} {str(u.admin)}', - f'{Color.yellow}[ignored]{Color.normal} {str(u.banned)}', - f'{Color.yellow}[is new]{Color.normal} {str(new_user)}', - f'{Color.yellow}[points]{Color.normal} {str(u.points)}', - f'{Color.yellow}[approved (tracker)]{Color.normal} {str(u.approved)}', - f'{Color.yellow}[invites (tracker)]{Color.normal} {str(u.invites)}', - f'{Color.yellow}[ignored]{Color.normal} {str(u.banned)}', - ] + if user_slice == '@' or user_slice == '~' or user_slice == '%' or user_slice == '+' or user_slice == ':' or user_slice == '&': + user_sliced = ampersand(line[i]) + # user_sliced = (line[i])[1:] + + else: + user_sliced = line[i] + #&kytv + # if line[i] not in user_list + print(f'USER SLICED {user_sliced}') + # db.create_all() + # for item in all_sites: + exists = Irc.query.filter_by(user=user_sliced).first() + if not exists: + timestamp_x = "{:%Y-%m-%d %H:%M:%S.%f}".format(datetime.now()) + timestamp_str = str(timestamp_x) + new_user = Irc(user=user_sliced, first_seen=timestamp_str, admin=admin, banned=False, points=0, welcomed=False, approved=False, tracker_code='', invites=0) + db.session.add(new_user) + db.session.commit() + + print(user_list) + user_list_string = (' ').join(user_list) + if len(new_added) > 0: + authed = f"{Color.yellow}now authorized: {(' ').join(new_added)}{Color.normal}" + send_irc_msg(self, authed, self.irc, send_to) + def mode_registered(self, line): + try: + if line[3] == ':+r': + print('USERNAME REGISTERED!') + state = f"Username already {username} registered. Please choose a different name." + # break + except Exception as e: + print(f"Error: {e}") + def say_hello(self, line): + if check_if_banned(self, line) == False: + send_to = where_to_send(line) + random.choice(self.hi) + msg = [] + c = (random.choice(self.hi)) + msg.append(f'{c}{Color.yellow} {tr}help for commands | {tr}help for info{Color.normal}') + for item in msg: + send_irc_msg(self, item, self.irc, send_to) + def new_user_add(self, line): + if check_if_banned(self, line) == False: + send_to = where_to_send(line) + msg = [] + for key in self.new_users: + self.new_users[key] = (self.new_users[key]) + 1 + def remaining_msg_irc(line, start, spacer, include_reason): + x = '' + n = start+1 + if len(line) > n: + for i in range(n, len(line)): + if i >= len(line) - 1: + end_space = '' + else: + end_space = ' ' + x = f'{x}{line[i]}{end_space}' + if spacer == True: + x = f' {x}' - msg.append(' | '.join(user_info)) - except Exception as e: - print(e) - msg.append(f"{admin_user} {com_err} not valid input") - else: - msg.append(f"{admin_user} {Color.yellow}[error]{Color.normal} enter a nick") - print(str(len(line))) - elif 'ignore' in line[4] or 'unignore' in line[4]: - reason, reason_msg = remaining_msg_irc(line, 5, False, True) - do_command = True - if len(line) >= 6: - try: - nick = line[5] - if line[4].lower() == 'ignore': - ban = True - ban_s = 'ignored' - else: - ban = False - ban_s = 'not ignored' - msg = [] - with app.app_context(): - # update = Irc.query.filter_by(user=u.user).first() - # update.welcomed = True - # db.session.commit() - - time_date_format = '%Y-%m-%d %H:%M:%S.%f' - with app.app_context(): - exists = Irc.query.filter_by(user=nick).first() - if not exists: - msg.append(f"{admin_user} {com_err} i don't know user {nick}") - else: - update = Irc.query.filter_by(user=nick).first() - update.banned = ban - db.session.commit() - msg.append(f'{admin_user} {com_msg} {ban_s} {nick} | {rs} {reason}') - command = [f'PRIVMSG MemoServ send {primary} {msg[0]}'] - - except Exception as e: - print(e) - msg.append(f"{admin_user} {com_err} not valid input") - else: - msg.append(f"{admin_user} {Color.yellow}[error]{Color.normal} enter a nick") - print(str(len(line))) - elif 'main_channel' in line[4]: - reason, reason_msg = remaining_msg_irc(line, 4, False, False) - do_command = False - print(reason) - - if len(line) >= 6 and (line[5])[:1] == '#': - try: - chan = str(line[5]) - chan_list = string_to_list(reason) - bad = 0 - for item in chan_list: - if item[:1] != '#': - bad += 1 - if bad > 0: - msg.append(f"{admin_user} {com_err} not valid input, channels must start with #") - else: - if len(chan_list) > 1: - s = 's' - else: - s = '' - if len(chan_list) >= 7: - msg.append(f"{admin_user} {com_err} too many channels. max of 5.") - else: - msg.append(f"{admin_user} {com_msg} primary channel{s}: {reason}") - self.channel_join = chan_list - irc_setting_update('channel', 0, False, reason, 0, False) - - except Exception as e: - print(e) - msg.append(f"{admin_user} {com_err} not valid input, takes a channel name.") - else: - msg.append(f"{admin_user} {Color.yellow}[primary channel]{Color.normal} {' '.join(self.channel_join)}") - - print(str(len(line))) - elif 'command' in line[4]: - do_command = True - reason, reason_msg = remaining_msg_irc(line, 4, True, True) - do_command = True - msg.append(f"{admin_user} {com_msg} irc command {com_msg}{reason_msg}") - command = [reason] - - else: - msg.append(f"{Color.light_red}i don't know how to do that :({Color.normal}") - for item in msg: - send_irc_msg(self, item, self.irc, send_to) - if do_command == True: - for item in command: - irc_command(item, self) - except Exception as e: - msg_1 = f'do {tr}admin or {tr}admin help for command list' - send_irc_msg(self, msg_1, self.irc, send_to) - else: - msg_1 = f'{Color.yellow}not authorized πŸ€”{Color.normal}' - names = f'NAMES {line[2]}\r\n'.encode(encoding='UTF-8',errors='strict') - self.irc.send (names) - send_irc_msg(self, msg_1, self.irc, send_to) - def help_menu(self, line): - if check_if_banned(self, line) == False: - send_to = where_to_send(line) + y = f"{x}" + else: + y = f' none given.' + return x, y + def register_user(username, newpassword): + irc_command(f"PRIVMSG NickServ register {newpassword} {username}@mail.i2p\r\n", self) + # REG = (bytes(f'PRIVMSG NickServ register {newpassword} {username}@mail.i2p\r\n', "UTF-8")) + # self.irc.send (REG) + def new_user_timer_joined(self, line): + if check_if_banned(self, line) == False: + send_to = where_to_send(line) + msg = [] - try: - if 'information' in line[4]: - msg = [f'gives info on the bot.'] - elif 'info' in line[4]: - msg = [f'gives info on the bot.'] - elif 'status' in line[4]: - msg = [f'gives status info on the bot.'] - elif 'admin' in line[4]: - msg = [f"do {tr}admin help to see those commands."] - else: - msg = [f"{Color.light_red}i don't know how to do that :({Color.normal}"] - except Exception as e: - print(e) - command_list = [ - f'{tr}info', - f'{tr}status', - f'{tr}admin', - ] - msg = [f"{Color.pink}[commands: do {tr}help for info]{Color.normal} {' | '.join(command_list)} | {Color.yellow}[respond in pms or channel]{Color.normal}"] - msg.append(f"{Color.pink}[more info]{Color.normal} {self.info_link}") - msg.append(f"{Color.pink}[web version]{Color.normal} {self.site_link}") - for item in msg: - send_irc_msg(self, item, self.irc, send_to) - # msg = [f'use {tr}commands to see a list | do {tr}help for info on that command'] - def info(self, line): - if check_if_banned(self, line) == False: - send_to = where_to_send(line) - msg = [ - f'i follow {str(len(feed_url))} RSS feeds accross i2p for updates.', - f'message {primary} if you want your feed added here. It must be accessible within i2p', - ] - for item in msg: - send_irc_msg(self, item, self.irc, send_to) - def status(self, line): - if check_if_banned(self, line) == False: - send_to = where_to_send(line) - msg = [] - if self.first_run == True: - msg = [f"I'm doing a fresh run and checking all feeds now. {Color.yellow}[{str(self.feed_count)}/{str(len(self.feed_dict))}]{Color.normal} rss feeds updated."] - else: - msg = [f"I've finished my initial checks. I've found {str(self.new_posts)} new posts so far."] - for item in msg: - send_irc_msg(self, item, self.irc, send_to) - while not exit_event.is_set(): - self.last_ping = time.time() - def new_user_timer(exit_event, self, send_to, irc, u): - while not exit_event.is_set(): - msg = [] - time.sleep(self.new_user_greeting) - with app.app_context(): - try: - if self.new_users[u.user] <= 0: - n = random.choice(self.greetings) - end = random.choice(self.greetings_end) - greeting = f'{Color.yellow}{n} {u.user}{end}{Color.normal}' - msg.append(greeting) - if u.user in self.new_users: - self.new_users.pop(u.user) - for item in self.new_user_message: - msg.append(item) - for item in msg: - send_irc_msg(self, item, self.irc, send_to) - print(f'Threads: {threading.active_count()}') - update = Irc.query.filter_by(user=u.user).first() - update.welcomed = True - db.session.commit() - except Exception as e: - print(e) + time_date_format = '%Y-%m-%d %H:%M:%S.%f' + joined_named = ((line[0]).split('!')[0])[1:] + with app.app_context(): + exists = Irc.query.filter_by(user=joined_named).first() + if exists: - exit_event.set() - sys.exit() + u = Irc.query.filter_by(user=joined_named).first() + time_obj = datetime.strptime(u.first_seen, time_date_format) + last_seen_str = time_obj.strftime('%d-%m-%Y') + time_now_obj = datetime.now() + difference = time_now_obj - time_obj + time_difference = timedelta(minutes=self.new_user_time) + if difference < time_difference and u.welcomed == False: + # msg.append(f'new user') + if joined_named not in self.new_users: + self.new_users[joined_named] = 0 - def irc_user_db(user): - with app.app_context(): - exists = Irc.query.filter_by(user=user).first() - if exists: - u = Irc.query.filter_by(user=user).first() - return u - else: - return False - readbuffer="" - try: - readbuffer=readbuffer+self.irc.recv(1024).decode("UTF-8") - temp=str.split(sanitize_input(readbuffer), "\n") - readbuffer=temp.pop( ) - for line in temp: - line=str.rstrip(line) - line=str.split(line) - x = ' '.join(line) - print(x) - if line[0] == 'PING': - ping(self, line) - elif line[1] == 'MODE': - mode_registered(self, line) - elif (username in line or f':{username}' in line) and line[1] == 'PRIVMSG' and line[2] != username: - say_hello(self, line) - elif ((line[0]).split('!')[0])[1:] not in self.new_users and line[1] == 'PRIVMSG' and line[2] != username and (line[3])[:2] != f':{tr}': - new_user_add(self, line) - elif ((line[0]).split('!')[0])[1:] in self.new_users and line[1] == 'PRIVMSG' and line[2] != username and (line[3])[:2] != f':{tr}': - new_user_timer_joined(self, line) - elif line[1] == 'JOIN': - join_chan(self, line) - elif line[1] == '353' and line[2] == username: - new_user(self, line) - elif line[1] == 'NOTICE' and line[2] == username: - register_bot(self, line) - elif line[1] == '451' and line[2] == username: - register_bot(self, line) - elif len(line) > 3: - if len(line[3]) > 2: - if (line[3])[1:] == f'{tr}admin': - admin(self, line) - elif (line[3])[1:] == f'{tr}help': - help_menu(self, line) - elif (line[3])[1:] == f'{tr}info': - info(self, line) - elif (line[3])[1:] == f'{tr}status': - status(self, line) - elif (time.time() - self.last_ping) > self.ping_timeout: - Irc_bot(username, password, hostname, port, channel, i2p_tracker_list, i2p_imdb_list, i2p_invidious_list, http_tunnel, primary, auth_users, instance_url, qoutes_path) - break - except Exception as e: - print(f"Error: {e}") - return(state) - self.irc = irc_connect(self.username, self.password, self.hostname, self.port) - - time.sleep(7) - JOI = f'JOIN {self.channel_join}\r\n' - JOIN = JOI.encode(encoding='UTF-8',errors='strict') - PASS = f'PRIVMSG NickServ IDENTIFY {self.password}\r\n' - PASSED = PASS.encode(encoding='UTF-8',errors='strict') - irc_command(f'PRIVMSG NickServ IDENTIFY {self.password}', self) - time.sleep(0.5) - irc_command(f'PRIVMSG NickServ GHOST {self.username} {self.password}', self) - time.sleep(0.5) - irc_command(f'MODE {self.username} +B', self) - ##### - #start threads - ##### - exit_event = threading.Event() - irc_rec = threading.Thread(target=irc_rec, args=(exit_event, self, self.username, self.password, self.hostname, self.port, channel, http_tunnel, primary, auth_users)) - irc_rec.start() + exit_timer = threading.Event() + thread_timer = threading.Thread(target=new_user_timer, args=(exit_timer, self, send_to, self.irc, u)) + thread_timer.start() + else: + if joined_named in self.new_users: + self.new_users.pop(joined_named) + # msg.append(f'no longer new user: {joined_named}') + else: + # msg.append(f'new user') + if joined_named not in self.new_users: + self.new_users[joined_named] = 0 + time_now_obj = datetime.now() - exit_throttle = threading.Event() - thread_throttle = threading.Thread(target=send_throttle, args=(exit_throttle, self)) - thread_throttle.start() + exit_timer = threading.Event() + thread_timer = threading.Thread(target=new_user_timer, args=(exit_timer, self, send_to, self.irc, joined_named)) + thread_timer.start() - exit_rss = threading.Event() - exit_rss = threading.Thread(target=irc_rss_feed_control, args=(exit_rss, self)) - exit_rss.start() + + for item in msg: + send_irc_msg(self, item, self.irc, send_to) + def join_chan(self, line): + if check_if_banned(self, line) == False: + # send_to = where_to_send(line) + msg = [] + time_date_format = '%Y-%m-%d %H:%M:%S.%f' + joined_named = ((line[0]).split('!')[0])[1:] + send_to = (line[2])[1:] + with app.app_context(): + exists = Irc.query.filter_by(user=joined_named).first() + if exists: + + u = Irc.query.filter_by(user=joined_named).first() + time_obj = datetime.strptime(u.first_seen, time_date_format) + last_seen_str = time_obj.strftime('%d-%m-%Y') + time_now_obj = datetime.now() + difference = time_now_obj - time_obj + time_difference = timedelta(minutes=self.new_user_time) + if difference < time_difference: + # msg.append(f'new user') + if joined_named not in self.new_users: + self.new_users[joined_named] = 0 + # u = Newuser(joined_named, time_now_obj, 0) + else: + if joined_named in self.new_users: + self.new_users.pop(joined_named) + # msg.append(f'no longer new user: {joined_named}') + # for i in range(0, len(new_users)): + # if new_users[i] == joined_named: + # new_users.pop(i) + # msg.append(f'no longer new user: {joined_named}') + # msg.append(f'{u.user}, {last_seen_str}, {str(u.admin)}, {str(u.banned)}, {str(u.points)}') + else: + # msg.append(f'new user') + if joined_named not in self.new_users: + self.new_users[joined_named] = 0 + time_now_obj = datetime.now() + + for item in msg: + send_irc_msg(self, item, self.irc, send_to) + + names = f'NAMES {send_to}\r\n'.encode(encoding='UTF-8',errors='strict') + self.irc.send (names) + # send_irc_msg(self, msg, irc, send_to) + def identify_bot(self): + irc_command(f'PRIVMSG NickServ GHOST {self.username} {self.password}', self) + time.sleep(0.25) + irc_command(f'PRIVMSG NickServ IDENTIFY {self.password}', self) + time.sleep(.25) + for item in self.channel_join: + irc_command(f'JOIN {item}', self) + time.sleep(0.25) + irc_command(f'NAMES {item}', self) + time.sleep(0.25) + time.sleep(0.25) + irc_command(f'MODE {self.username} +B', self) + send_irc_msg(self, '', self.irc, 'username') + send_irc_msg(self, '', self.irc, 'username') + def register_bot(self, line): + user = ((line[0].split('!'))[0])[1:] + if line[1] == '451' and len(line) >= 4: + reg = [] + for i in range(4, len(line)): + reg.append(line[i]) + reg_s = ' '.join(reg) + print(reg_s) + register_user(username, password) + try: + if line[6] == "not" and line[7] == 'registered.': + register_user(username, password) + new_nick = True + elif line[3].lower() == ":if" and line[4].lower() == 'you': + identify_bot(self) + elif line[2] == 375: + identify_bot(self) + elif line[3].lower() == ":this" and line[6].lower() == 'registered.': + identify_bot(self) + elif user.lower() == 'nickserv': + if len(line) >=4: + reg = [] + for i in range(4, len(line)): + reg.append(line[i]) + reg_s = (' '.join(reg)).lower() + else: + reg_s = '' + if line[3].lower() == ':welcome': + identify_bot(self) + elif reg_s == 'is not a registered nickname.': + register_user(username, password) + new_nick = True + except Exception as e: + print(f"Error: {e}") + def admin(sefl, line): + do_command = False + send_to = where_to_send(line) + if ((line[0].split('!'))[0])[1:] in self.auth_users: + msg = [] + + try: + admin_user = f"{Color.pink}[admin {((line[0].split('!'))[0])[1:]}]{Color.normal}" + com_msg = f'{Color.yellow}[command]{Color.normal}' + com_err = f'{Color.light_red}[COMMAND ERROR]{Color.normal}' + rs = f'{Color.yellow}[reason]{Color.normal}' + ms = f'{Color.yellow}[msg]{Color.normal}' + + if 'help' in line[4]: + command_list = [ + f'part ', + f'join ', + f'refresh', + f'say ', + f'command ', + f'kill ', + f'check ', + f'ignore / unignore ', + f'{Color.yellow}[info]{Color.normal} accepts commands in a given channel or through pm. optional. command = raw irc command. ignored users are ignored by the bot.' + ] + + settings_list = [ + f'rss_feed_update ', + f'max_posts ', + 'main_channel <#channel>', + 'throttle ', + f'{Color.yellow}[info]{Color.normal} command without new gives current value. throttle is (s) between msg sends. main_channel is a list to join on connect, seperated by space or comma "#chan1 #chan2 #chan3' + ] + msg.append(f"{Color.yellow}[admin commands]{Color.normal} {' | '.join(command_list)}") + # msg.append(f"{Color.yellow}[tracker commands]{Color.normal} {' | '.join(tracker_commands)}") + msg.append(f"{Color.yellow}[admin settings]{Color.normal} {' | '.join(settings_list)}") + msg.append(f"{Color.yellow}[Preface all commands with {tr}admin]{Color.normal} ex: {tr}admin throttle 0.5 {Color.yellow}[more info]{Color.normal} {self.info_link}") + elif 'part' in line[4]: + reason, reason_msg = remaining_msg_irc(line, 5, True, True) + do_command = True + msg.append(f"{admin_user} {com_msg} part channel {line[5]} {rs}{reason_msg}") + time.sleep(self.throttle + 2) + command = [f'PRIVMSG MemoServ send {primary} {msg[0]}', f'PART {line[5]}{reason}'] + elif 'join' in line[4]: + do_command = True + msg.append(f"{admin_user} {com_msg} join channel {line[5]}") + msg.append(f'{Color.light_red}joining channel {line[5]} πŸ‘οΈπŸ‘„πŸ‘οΈ{Color.normal}') + command = [f'PRIVMSG MemoServ send {primary} {msg[0]}', f'JOIN {line[5]}'] + elif 'kill' in line[4]: + do_command = True + reason, reason_msg = remaining_msg_irc(line, 4, True, True) + do_command = True + msg.append(f"{admin_user} {com_msg} {Color.light_red}KILL{Color.normal} {rs}{reason_msg}") + msg.append(f'{Color.light_red}disconnecting 😴{Color.normal}') + time.sleep(self.throttle + 2) + command = [f'PRIVMSG MemoServ send {primary} {msg[0]}', f'QUIT {reason}'] + elif 'say' in line[4]: + do_command = True + reason, reason_msg = remaining_msg_irc(line, 5, True, True) + do_command = True + msg.append(f"{admin_user} {com_msg} say to {line[5]} {ms}{reason_msg}") + command = [f'PRIVMSG {line[5]} {reason}'] + + elif 'refresh' in line[4]: + do_command = False + get_feed_list(self) + msg.append(f"{admin_user} {com_msg} refreshing feed list.") + # command = [f'PRIVMSG {line[5]} {reason}'] + elif 'throttle' in line[4]: + reason, reason_msg = remaining_msg_irc(line, 4, False, False) + do_command = False + + if len(line) >= 6: + m = 5 + try: + new_time_f = float(line[5]) + if new_time_f <= m: + msg.append(f"{admin_user} {com_msg} send message throttle set to {line[5]}s") + self.throttle = new_time_f + irc_setting_update('throttle', 0, False, '', new_time_f, False) + else: + msg.append(f"{admin_user} {com_err} too long, {m}s max.") + + except Exception as e: + print(e) + msg.append(f"{admin_user} {com_err} not valid input, takes a float (seconds), 5s max.") + else: + msg.append(f"{admin_user} {Color.yellow}[message throttle]{Color.normal} {str(self.throttle)}s") + + print(str(len(line))) + elif 'feed_update' in line[4]: + reason, reason_msg = remaining_msg_irc(line, 4, False, False) + do_command = False + + if len(line) >= 6: + m = 60 + try: + new_time_f = float(line[5]) + if new_time_f >= m: + msg.append(f"{admin_user} {com_msg} checks all feeds in {line[5]}s") + self.rss_feed_update = new_time_f + irc_setting_update('rss_feed_update', 0, False, '', new_time_f, False) + else: + msg.append(f"{admin_user} {com_err} too short, {m}s min.") + + except Exception as e: + print(e) + msg.append(f"{admin_user} {com_err} not valid input, takes a float (seconds), 60s min.") + else: + msg.append(f"{admin_user} {Color.yellow}[Feed Update]{Color.normal} {str(self.rss_feed_update)}s") + elif 'max_posts' in line[4]: + reason, reason_msg = remaining_msg_irc(line, 4, False, False) + do_command = False + + if len(line) >= 6: + m = 50 + try: + new_setting = int(line[5]) + if new_setting <= m: + msg.append(f"{admin_user} {com_msg} set max post per feed per update at {line[5]}") + self.max_posts_per_pull = new_setting + irc_setting_update('max_posts_per_pull', new_setting, False, '', 0, False) + else: + msg.append(f"{admin_user} {com_err} too many {m} max.") + + except Exception as e: + print(e) + msg.append(f"{admin_user} {com_err} not valid input, takes an int {str(m)} max.") + else: + msg.append(f"{admin_user} {Color.yellow}[Max posts per pull]{Color.normal} {str(self.max_posts_per_pull)}") + print(str(len(line))) + elif 'check' in line[4]: + reason, reason_msg = remaining_msg_irc(line, 4, False, False) + do_command = False + if len(line) >= 6: + try: + nick = line[5] + msg = [] + with app.app_context(): + + + time_date_format = '%Y-%m-%d %H:%M:%S.%f' + with app.app_context(): + exists = Irc.query.filter_by(user=nick).first() + # exists = Irc.query.filter_by((func.lower(user) == nick.lower())).first() + if not exists: + msg.append(f"{admin_user} {com_err} i don't know user {nick}") + else: + # func.lower(countries.name) == name.lower(), + # func.lower(countries.capital) == capital.lower() + u = Irc.query.filter_by(user=nick).first() + time_obj = datetime.strptime(u.first_seen, time_date_format) + last_seen_str = time_obj.strftime('%d-%m-%Y') + time_now_obj = datetime.now() + difference = time_now_obj - time_obj + time_difference = timedelta(minutes=30) + if difference < time_difference: + new_user = True + else: + new_user = False + # user, first_seen, admin, banned, new, points + user_info = [ + f'{admin_user} {com_msg} user info', + f'{Color.yellow}[user]{Color.normal} {u.user}', + f'{Color.yellow}[first seen]{Color.normal} {last_seen_str}', + f'{Color.yellow}[admin]{Color.normal} {str(u.admin)}', + f'{Color.yellow}[ignored]{Color.normal} {str(u.banned)}', + f'{Color.yellow}[is new]{Color.normal} {str(new_user)}', + f'{Color.yellow}[points]{Color.normal} {str(u.points)}', + f'{Color.yellow}[approved (tracker)]{Color.normal} {str(u.approved)}', + f'{Color.yellow}[invites (tracker)]{Color.normal} {str(u.invites)}', + f'{Color.yellow}[ignored]{Color.normal} {str(u.banned)}', + ] + + msg.append(' | '.join(user_info)) + except Exception as e: + print(e) + msg.append(f"{admin_user} {com_err} not valid input") + else: + msg.append(f"{admin_user} {Color.yellow}[error]{Color.normal} enter a nick") + print(str(len(line))) + elif 'ignore' in line[4] or 'unignore' in line[4]: + reason, reason_msg = remaining_msg_irc(line, 5, False, True) + do_command = True + if len(line) >= 6: + try: + nick = line[5] + if line[4].lower() == 'ignore': + ban = True + ban_s = 'ignored' + else: + ban = False + ban_s = 'not ignored' + msg = [] + with app.app_context(): + # update = Irc.query.filter_by(user=u.user).first() + # update.welcomed = True + # db.session.commit() + + time_date_format = '%Y-%m-%d %H:%M:%S.%f' + with app.app_context(): + exists = Irc.query.filter_by(user=nick).first() + if not exists: + msg.append(f"{admin_user} {com_err} i don't know user {nick}") + else: + update = Irc.query.filter_by(user=nick).first() + update.banned = ban + db.session.commit() + msg.append(f'{admin_user} {com_msg} {ban_s} {nick} | {rs} {reason}') + command = [f'PRIVMSG MemoServ send {primary} {msg[0]}'] + + except Exception as e: + print(e) + msg.append(f"{admin_user} {com_err} not valid input") + else: + msg.append(f"{admin_user} {Color.yellow}[error]{Color.normal} enter a nick") + print(str(len(line))) + elif 'main_channel' in line[4]: + reason, reason_msg = remaining_msg_irc(line, 4, False, False) + do_command = False + print(reason) + + if len(line) >= 6 and (line[5])[:1] == '#': + try: + chan = str(line[5]) + chan_list = string_to_list(reason) + bad = 0 + for item in chan_list: + if item[:1] != '#': + bad += 1 + if bad > 0: + msg.append(f"{admin_user} {com_err} not valid input, channels must start with #") + else: + if len(chan_list) > 1: + s = 's' + else: + s = '' + if len(chan_list) >= 7: + msg.append(f"{admin_user} {com_err} too many channels. max of 5.") + else: + msg.append(f"{admin_user} {com_msg} primary channel{s}: {reason}") + self.channel_join = chan_list + irc_setting_update('channel', 0, False, reason, 0, False) + + except Exception as e: + print(e) + msg.append(f"{admin_user} {com_err} not valid input, takes a channel name.") + else: + msg.append(f"{admin_user} {Color.yellow}[primary channel]{Color.normal} {' '.join(self.channel_join)}") + + print(str(len(line))) + elif 'command' in line[4]: + do_command = True + reason, reason_msg = remaining_msg_irc(line, 4, True, True) + do_command = True + msg.append(f"{admin_user} {com_msg} irc command {com_msg}{reason_msg}") + command = [reason] + + else: + msg.append(f"{Color.light_red}i don't know how to do that :({Color.normal}") + for item in msg: + send_irc_msg(self, item, self.irc, send_to) + if do_command == True: + for item in command: + irc_command(item, self) + except Exception as e: + msg_1 = f'do {tr}admin or {tr}admin help for command list' + send_irc_msg(self, msg_1, self.irc, send_to) + else: + msg_1 = f'{Color.yellow}not authorized πŸ€”{Color.normal}' + names = f'NAMES {line[2]}\r\n'.encode(encoding='UTF-8',errors='strict') + self.irc.send (names) + send_irc_msg(self, msg_1, self.irc, send_to) + def help_menu(self, line): + if check_if_banned(self, line) == False: + send_to = where_to_send(line) + + try: + if 'information' in line[4]: + msg = [f'gives info on the bot.'] + elif 'info' in line[4]: + msg = [f'gives info on the bot.'] + elif 'status' in line[4]: + msg = [f'gives status info on the bot.'] + elif 'admin' in line[4]: + msg = [f"do {tr}admin help to see those commands."] + else: + msg = [f"{Color.light_red}i don't know how to do that :({Color.normal}"] + except Exception as e: + print(e) + command_list = [ + f'{tr}info', + f'{tr}status', + f'{tr}admin', + ] + msg = [f"{Color.pink}[commands: do {tr}help for info]{Color.normal} {' | '.join(command_list)} | {Color.yellow}[respond in pms or channel]{Color.normal}"] + msg.append(f"{Color.pink}[more info]{Color.normal} {self.info_link}") + msg.append(f"{Color.pink}[web version]{Color.normal} {self.site_link}") + for item in msg: + send_irc_msg(self, item, self.irc, send_to) + # msg = [f'use {tr}commands to see a list | do {tr}help for info on that command'] + def info(self, line): + if check_if_banned(self, line) == False: + send_to = where_to_send(line) + msg = [ + f'i follow {str(len(feed_url))} RSS feeds accross i2p for updates.', + f'message an OP if you want your feed added here. It must be accessible within i2p', + ] + for item in msg: + send_irc_msg(self, item, self.irc, send_to) + def status(self, line): + if check_if_banned(self, line) == False: + send_to = where_to_send(line) + msg = [] + if self.first_run == True: + msg = [f"I'm doing a fresh run and checking all feeds now. {Color.yellow}[{str(self.feed_count)}/{str(len(self.feed_dict))}]{Color.normal} rss feeds updated."] + else: + msg = [f"I've finished my initial checks. I've found {str(self.new_posts)} new posts so far."] + for item in msg: + send_irc_msg(self, item, self.irc, send_to) + while not exit_event.is_set(): + self.last_ping = time.time() + def new_user_timer(exit_event, self, send_to, irc, u): + while not exit_event.is_set(): + msg = [] + time.sleep(self.new_user_greeting) + with app.app_context(): + try: + if self.new_users[u.user] <= 0: + n = random.choice(self.greetings) + end = random.choice(self.greetings_end) + greeting = f'{Color.yellow}{n} {u.user}{end}{Color.normal}' + msg.append(greeting) + if u.user in self.new_users: + self.new_users.pop(u.user) + for item in self.new_user_message: + msg.append(item) + for item in msg: + send_irc_msg(self, item, self.irc, send_to) + print(f'Threads: {threading.active_count()}') + update = Irc.query.filter_by(user=u.user).first() + update.welcomed = True + db.session.commit() + except Exception as e: + print(e) + + exit_event.set() + sys.exit() + + def irc_user_db(user): + with app.app_context(): + exists = Irc.query.filter_by(user=user).first() + if exists: + u = Irc.query.filter_by(user=user).first() + return u + else: + return False + readbuffer="" + try: + readbuffer=readbuffer+self.irc.recv(1024).decode("UTF-8") + temp=str.split(sanitize_input(readbuffer), "\n") + readbuffer=temp.pop( ) + for line in temp: + line=str.rstrip(line) + line=str.split(line) + x = ' '.join(line) + print(x) + if line[0] == 'PING': + ping(self, line) + elif line[1] == 'MODE': + mode_registered(self, line) + elif (username in line or f':{username}' in line) and line[1] == 'PRIVMSG' and line[2] != username: + say_hello(self, line) + elif ((line[0]).split('!')[0])[1:] not in self.new_users and line[1] == 'PRIVMSG' and line[2] != username and (line[3])[:2] != f':{tr}': + new_user_add(self, line) + elif ((line[0]).split('!')[0])[1:] in self.new_users and line[1] == 'PRIVMSG' and line[2] != username and (line[3])[:2] != f':{tr}': + new_user_timer_joined(self, line) + elif line[1] == 'JOIN': + join_chan(self, line) + elif line[1] == '353' and line[2] == username: + new_user(self, line) + elif line[1] == 'NOTICE' and line[2] == username: + register_bot(self, line) + elif line[1] == '451' and line[2] == username: + register_bot(self, line) + elif line[1] == '376' or line[1] == '266': + print('IDENTIFY BOT') + identify_bot(self) + elif len(line) > 3: + if len(line[3]) > 2: + if (line[3])[1:] == f'{tr}admin': + admin(self, line) + elif (line[3])[1:] == f'{tr}help': + help_menu(self, line) + elif (line[3])[1:] == f'{tr}info': + info(self, line) + elif (line[3])[1:] == f'{tr}status': + status(self, line) + elif (time.time() - self.last_ping) > self.ping_timeout: + Irc_bot(username, password, hostname, port, channel, i2p_tracker_list, i2p_imdb_list, i2p_invidious_list, http_tunnel, primary, auth_users, instance_url, qoutes_path) + break + except Exception as e: + print(f"Error: {e}") + return(state) + self.irc = irc_connect(self.username, self.password, self.hostname, self.port) + + time.sleep(5) + JOI = f'JOIN {self.channel_join}\r\n' + JOIN = JOI.encode(encoding='UTF-8',errors='strict') + PASS = f'PRIVMSG NickServ IDENTIFY {self.password}\r\n' + PASSED = PASS.encode(encoding='UTF-8',errors='strict') + irc_command(f'PRIVMSG NickServ IDENTIFY {self.password}', self) + time.sleep(0.5) + irc_command(f'PRIVMSG NickServ GHOST {self.username} {self.password}', self) + time.sleep(0.5) + irc_command(f'MODE {self.username} +B', self) + ##### + #start threads + ##### + exit_event = threading.Event() + irc_rec = threading.Thread(target=irc_rec, args=(exit_event, self, self.username, self.password, self.hostname, self.port, channel, http_tunnel, primary, auth_users)) + irc_rec.start() + + exit_throttle = threading.Event() + thread_throttle = threading.Thread(target=send_throttle, args=(exit_throttle, self)) + thread_throttle.start() + + exit_rss = threading.Event() + exit_rss = threading.Thread(target=irc_rss_feed_control, args=(exit_rss, self)) + exit_rss.start() Irc_bot(news_bot, news_pass, hostname, news_port, channel, primary, auth_users, http_tunnel, bot_send) ############# # end IRC bot ############# if __name__ == '__main__': - app.run(host='127.0.0.1', port=news_rss_port) - app.run(debug=True) \ No newline at end of file + app.run(host='127.0.0.1', port=news_rss_port) + app.run(debug=True) \ No newline at end of file diff --git a/changelognewsbot.txt b/changelognewsbot.txt index 0b14348..9008706 100755 --- a/changelognewsbot.txt +++ b/changelognewsbot.txt @@ -1,3 +1,6 @@ +19/9/2025: added better parsing for terminus.i2p and rss feeds from gitea, separate "clean" channel (no torrents) +18/09/2025: added 25 new rss feeds, removed some dead ones +28/03/2025: added rss feeds from git.simp.i2p along with other new feeds, fixed another bug with html code showing up correctly, updated footer 21/01/2025: Improvements in parsing urls and html tags 08/12/2024: CSS improvements, thank you to dr|z3d, bug fixes 30/11/2024: Live testing in IRC, added /feedlinks so alive feeds can be copied as a list diff --git a/functions.py b/functions.py index 59393cf..cd50cac 100755 --- a/functions.py +++ b/functions.py @@ -295,7 +295,7 @@ def format_msg(single_msg_raw, topic): post_url = f'http://{nick_raw}{l[i][2:]}' else: post_url = (single_msg.split('::')[1]).split(' @@@')[0] - if get_host(post_url).casefold() == '127.0.0.1': + if get_host(post_url) == '127.0.0.1': url_q = post_url.split(get_short_url(post_url))[1] post_url = f'http://{nick_raw}{url_q}' l[i] = '' diff --git a/rsslist.txt b/rsslist.txt index d75c859..d26ef56 100755 --- a/rsslist.txt +++ b/rsslist.txt @@ -1,12 +1,10 @@ http://simp.i2p/feed torrents http://righttoprivacy.i2p/rss/ blog http://angelwood.i2p/feed.rss blog -http://gl6vzyjnv62kp3vjmmouwlvsrbp2bujk2cev6frgnln5vfepy2xq.b32.i2p/index.xml blog http://dujemihanovic.i2p/index.xml blog http://torrentfreak.i2p/feed/ torrents http://arstechnica.i2p/feed news http://simp.i2p/blog/feed blog -http://ghativega.i2p/atom.xml blog http://cool-website.i2p/rss.xml blog http://jacksonchen666.i2p/feeds/ blog http://mdleom.i2p/atom.xml blog @@ -19,9 +17,7 @@ http://ellipticnews.i2p/feeds/posts/default blog http://kuukkanen.i2p/feed.xml blog http://hackaday.i2p/feed news http://hongkongfreepress.i2p/ news -http://git.idk.i2p/i2p-hackers/i2p.i2p/-/merge_requests.atom?state=opened developer http://zzz.i2p/topics.rss forum -http://git.idk.i2p/i2p-hackers/i2p.i2p/-/issues.atom?state=opened developer http://stats.i2p/cgi-bin/newhosts.xml blog http://tracker2.postman.i2p/?view=RSS&mapset=-1 torrents http://hq.postman.i2p/?feed=atom blog @@ -36,7 +32,6 @@ http://tails.i2p/news/index.en.atom blog http://discuss.i2p/app.php/feed/forums?sid=69da73f2a323f778252a08a4c93a887d forum http://sciencedaily.i2p/rss news http://schneieronsecurity.i2p/rss news -http://orizuru.i2p/atom.xml news http://s-config.i2p/rss blog http://shreddit.i2p/r/i2p/.rss forum http://natter.i2p/StormyCloudInc/rss forum @@ -51,27 +46,60 @@ http://techxplore.i2p/rss-feed/ news http://notbob.i2p/blog.xml blog http://theatlantic.i2p/feed/all/ news http://i2p-projekt.i2p/en/feed/blog/atom developer -http://amnesie.i2p/rss.xml blog http://1337z.i2p/rss.xml blog http://git.skank.i2p/rez/plus.atom developer http://hackernews.i2p/rss news http://paltepuk.i2p/blog/index.i2p.xml blog http://deurachavich.i2p/rss.xml blog -http://fury.i2p/feed.xml blog -https://blog.everypizza.im/feed/feed.xml blog -http://mdleom.i2p/atom.xml blog -http://masflam.i2p/blog/feed.rss blog http://libresolutionsnetwork.i2p/rss blog http://jacksonchen666.i2p/posts/index.xml blog http://dankaminsky.i2p/feed blog -http://darkrealm.i2p/index.php?act=rss blog http://franciscogg.i2p/rss.xml blog http://shadowforums.i2p/!feed forum +http://darkrealm.i2p/index.php?act=rss blog http://kulervod.i2p/feeds/local.xml?sort=Active forum http://git.simp.i2p/simp/rayhunter.rss developer +http://git.simp.i2p/simp/guessthesong.rss developer http://git.simp.i2p/fuzzykitten/dev_endboard.rss developer http://git.simp.i2p/simp/i2music.rss developer http://git.simp.i2p/simp/i2pnews.rss developer http://git.simp.i2p/simp/shorturl.rss developer -http://taz.i2p/rss.xml blog -http://forum.midgard.i2p/syndication.php forum +http://git.simp.i2p/simp/TuckIt.rss developer +http://terminus.i2p/rss forum +http://git.idk.i2p/I2P_Developers/i2p.i2p.rss developer +http://git.idk.i2p/idk/Go_I2p.rss developer +http://git.idk.i2p/I2P_Developers/i2p.plugins.zzzot.rss developer +http://git.idk.i2p/idk/I2PSnark-RPC.rss developer +http://git.community.i2p/PurpleI2P/pyseeder.rss developer +http://git.community.i2p/PurpleI2P/i2pd-tools.rss developer +http://git.community.i2p/PurpleI2P/i2pd.rss developer +http://gatheryourparty.i2p/rss.xml blog +http://monkemanx.i2p/index.xml blog +http://masflam.i2p/feed/ blog +http://thricegreat.i2p/rss.xml blog +http://taiwan.i2p/rss2.xml blog +http://shittyweb.i2p/blog/feed.xml blog +http://silosneeded.i2p/feed.xml blog +http://pabloshell.i2p/rss.xml blog +http://masflam.i2p/feed/?type=rss blog +http://maidzone.i2p/blog.rss blog +http://med0ed.i2p/rss.xml blog +http://jerryhome.i2p/atom.xml blog +http://lulu-cats.i2p/index.xml blog +http://joshuatshaffer.i2p/index.xml blog +http://jakob.i2p/feed.xml blog +http://itphx.i2p/feed blog +http://gettie.i2p/rss.xml blog +http://darksavantcrusaders.i2p/feed.xml blog +http://cxj.i2p/index.xml blog +http://cosmicflow.i2p/rss/news.xml blog +http://gedanken.i2p/feed.rss blog +http://iranfreedom.i2p/en/feed/ news +http://opendemocracy.i2p/feed news +http://sur.i2p/feed news +http://upstreamjournal.i2p/feed news +http://clap.i2p/feed news +http://git.simp.i2p/simp/Eepstore.rss developer +http://git.simp.i2p/simp/emissary.rss developer +http://git.simp.i2p/simp/mantaray.rss developer +http://git.simp.i2p/simp/yosemite.rss developer \ No newline at end of file