# This is the code behind Helpful Jew.

# Helpful Jew is a Telegram bot that parses RSS feeds
# and sends notifications when new entry is found

# The name "Helpful Jew" was chosed to fight anti-semitism
# People should know that Jews are not evil
# and that Jews want to help others.

# Created by KuchiKuu
# 2022-04-16
# Modified: 2020-04-21

import feedparser
import telebot
import threading # for RSS feed to check from time to time
import time # for sleep
import json
config = {}
TOKEN=""
OWNER_ID=-1

with open("/root/telegram/helpfuljew/helpfuljew_config") as f:
	config = json.load(f)
TOKEN=config["TOKEN"]
OWNER_ID=config["OWNER_ID"]

# file structure:
#  feeds - contains JSON of RSS_FEED: [groupID,groupID]
#  entries - contains hashed values of posts already sent

feeds = {}
entries = []
with open("/root/telegram/helpfuljew/helpfuljew_feeds") as f:
	feeds = json.load(f)
with open("/root/telegram/helpfuljew/helpfuljew_entries") as f:
	entries = json.load(f)

def debug_message(text):
	print(text)


#exit()
def json_save_feeds():
	with open("/root/telegram/helpfuljew/helpfuljew_feeds","w") as f:
		json.dump(feeds,f)
def json_save_entries():
	with open("/root/telegram/helpfuljew/helpfuljew_entries","w") as f:
		json.dump(entries,f)
def populate_entries():
	for address in feeds.keys():
		fetch_first_time(address)
def check_entry_to_not_shit_itself_and_return_valid_hash(entry):
	hash=""
	if "title" in entry.keys():
		hash+=entry.title
	if "published" in entry.keys():
		hash+=" "+entry.published
	if "id" in entry.keys():
		hash+=" "+entry.id
	#print(hash)
	return hash

def fetch_first_time(fetch_first_time_address):
	entries_number=0
	fetch_first_time_feed = feedparser.parse(fetch_first_time_address);
	for entry in fetch_first_time_feed['entries']:
		#hash=entry['title']+" "+entry['published']+" "+entry['id']
		hash=check_entry_to_not_shit_itself_and_return_valid_hash(entry)
		if hash not in entries:
			entries.append(hash)
			entries_number=entries_number+1
	json_save_entries()
	debug_message("Saved "+str(entries_number)+" from "+fetch_first_time_address)

def force_check_feeds(filler=1):
	if(filler==1):
		check_feeds_feeds = feeds
		check_feeds_entries = entries
		debug_message("Checking feeds")
		if(len(check_feeds_feeds.keys())>0):
			for address in check_feeds_feeds.keys():
				bot.send_message(OWNER_ID,"Checking "+str(address))
				feed=feedparser.parse(address)
				for entry in feed['entries']:
					#print(entry['title']+" "+entry['published']+" "+entry['id']);
					#hash=entry['title']+" "+entry['published']+" "+entry['id']
					hash=check_entry_to_not_shit_itself_and_return_valid_hash(entry)
					if hash not in entries:
						for group in check_feeds_feeds[address]:
							text="*"+feed["feed"]["title"]+"*\nNew entry!\n\n"+entry["title"]+"\n"
							text+=entry["summary"][:100]
							text+="...\n"+entry['link']
							bot.send_message(group,text);
						entries.append(hash)
						json_save_entries()
	bot.send_message(OWNER_ID,"Checking done")

def check_feeds(wait_time=3600,forever=1):
	while(1):
		check_feeds_feeds = feeds
		check_feeds_entries = entries
		debug_message("Checking feeds")
		if(len(check_feeds_feeds.keys())>0):
			for address in check_feeds_feeds.keys():
				debug_message("Checking "+str(address))
				feed=feedparser.parse(address)
				for entry in feed['entries']:
					#print(entry['title']+" "+entry['published']+" "+entry['id']);
					#hash=entry['title']+" "+entry['published']+" "+entry['id']
					hash=check_entry_to_not_shit_itself_and_return_valid_hash(entry)
					if hash not in entries:
						for group in check_feeds_feeds[address]:
							text="*"+feed["feed"]["title"]+"*\nNew entry!\n\n"+entry["title"]+"\n"+entry["summary"][:100]+"...\n"+entry['link']
							bot.send_message(group,text);
						entries.append(hash)
						json_save_entries()
		debug_message("Checking done. Sleeping...")
		time.sleep(wait_time);


if(len(feeds.keys())>0):
	debug_message(f'{len(feeds.keys())} feeds in database')
	if(len(entries)==0):
		debug_message("Entries are empty. Populating...")
		populate_entries()
	else:
		debug_message("feeds are empty")

bot = telebot.TeleBot(TOKEN,parse_mode=None)

@bot.message_handler(commands=['follow','remove','list','myid','check','reminder'])
def database_management_yolo(message):
	#print(message)
	command = message.text.split(" ")
	if(command[0] == "/check"):
		if(message.from_user.id == OWNER_ID):
			bot.reply_to(message,"OK")
			force_check_feeds()
	if(command[0] == "/reminder"):
		bot.send_message(message.chat.id,"A friendly reminder:\nIt's all my fault.")
	if(command[0] == "/myid"):
		bot.reply_to(message,"Your ID: "+str(message.from_user.id))
	if(command[0] == "/follow"):
		if(len(command[1])>0):
			feed_address = command[1]
			check_feed = feedparser.parse(command[1])
			if(len(check_feed["entries"])==0):
				bot.reply_to(message,"Oy vey! This does not look like a valid RSS!")
			else:
				if feed_address in feeds.keys():
					if message.chat.id not in feeds[feed_address]:
						feeds[feed_address].append(message.chat.id)
						bot.reply_to(message,"Following: "+feed_address)
						fetch_first_time(feed_address)
					else:
						bot.reply_to(message,"I already follow this feed for you.")
				else:
					feeds[feed_address] = [message.chat.id]
					bot.reply_to(message,"Following: "+feed_address)
					fetch_first_time(feed_address)

			#bot.reply_to(message,str(json.dumps(feeds)))
				json_save_feeds();
	if(command[0] == "/remove"):
		if(len(command[1])>0):
			feeds[command[1]].remove(message.chat.id)
			if(len(feeds[command[1]]) == 0):
				feeds.pop(command[1])
				debug_message("No one else follows "+str(command[1]))
			bot.reply_to(message,"Removing: "+command[1])
			json_save_feeds()
	if(command[0] == "/list"):
		list_feeds = ""
		for i in feeds.keys():
			if message.chat.id in feeds[i]:
				list_feeds = list_feeds + str(i) + "\n"
			pass
		if(list_feeds == ""):
			bot.reply_to(message,"Oy vey! You do not follow any feeds!")
		else:
			bot.reply_to(message,"Your feeds:\n"+str(list_feeds))

#@bot.message_handler(func=lambda m: True)
#def echo_all(message):
#	print("Got a message: " + str(message))
#	bot.reply_to(message,str(bot.get_me()))

#@bot.channel_post_handler(func=lambda m:True)
#def reply_to_post(message):
#	bot.reply_to(message,str(bot.get_Me()))

@bot.my_chat_member_handler()
def membership(ChatMemberUpdated):
	if(ChatMemberUpdated.new_chat_member.user.id == bot.get_me().id):
		if(ChatMemberUpdated.new_chat_member.status == "member"):
			debug_message("I have joined a chat")
			bot.send_message(ChatMemberUpdated.chat.id,"Asalamalaykum my brothers.")
		elif(ChatMemberUpdated.new_chat_member.status == "left"):
			debug_message("I have been removed from a chat.")

x = threading.Thread(target=check_feeds)
x.start()

bot.infinity_polling()