import argparse
import datetime
import os.path
import re
import subprocess
import sys
import time
import urllib
import urllib.request
from urllib.error import URLError, HTTPError
from lxml import etree
from pushbullet import PushBullet
def initial_arg():
	argparser = argparse.ArgumentParser(description='nowere.py --param')
	argparser.add_argument('--notif', help='Notify about new posts after last visit only', action='store_true')
	argparser.add_argument('--text-only', help='Send notification with post text only', action='store_true')
	argparser.add_argument('--text-image', help='Send notification with post text and image', action='store_true')
	start_arg = None
	args, unknown = argparser.parse_known_args()
	if len(unknown) != 0:  # еррор кондишион и выход, непонятные арги
		print(f'Unknown args {unknown}')
		argparser.print_help(sys.stderr)
		sys.exit(1)
	if (len(sys.argv)) == 2:  # Проверка на один единственный арг, первый само имя скрипта
		for arg in vars(args):  # перебор и поиск введенного арга
			if getattr(args, arg):
				start_arg = arg
				print(f'Starting arg is --{start_arg}')
				break
	else:
		start_arg = 'text_only'
		print(
			f'Starting arg is --{start_arg}')  # сработает без аргументов, дефолт значение, либо выдавать инфо и выходить, нижние две строки
		# argparser.print_help(sys.stderr)
		# sys.exit(1)
	del argparser, args, unknown
	return start_arg
def parse_post(number, text):
	if Last_reported < number:
		root = etree.HTML(text)
		path = root.find('.//td[@id="reply%d"]' % number)
		OP_post_tag = 0
		if path is None:
			OP_post_tag = 1
		image_url = None
		blockquote_mark = 0
		post_text = str()
		picture_path = None
		if OP_post_tag == 1:
			path = root.find('.//form[@id="delform"]')
		for i in path.iter():
			if i.attrib.get('class') == 'filetitle':
				thread_name = i.text
				post_text = post_text + f'New thread started, title : {thread_name}\n'
			elif i.attrib.get('target') == '_blank':
				if start_arg == 'text_image':
					if image_url is None:
						image_url = f'https://nowere.net{i.attrib.get("href")}'
						image_name = image_url[-17:]
						picture_request = urllib.request.urlretrieve(f'{image_url}', f'pics/{image_name}')
						picture_path = f'pics/{image_name}'
						post_text = post_text + f'Picture attached with post, name: {image_name}\n'
					else:
						continue
				else:
					continue
			elif i.attrib.get('class') == 'omittedposts':
				break
			elif i.tag == 'table':
				break
			elif i.attrib.get('clear') == 'left':
				break
			elif i.tag == 'blockquote':
				blockquote_mark = 1
			if blockquote_mark == 1:
				# TODO Comment is too long
				if i.tag == 'div':
					blockquote_mark = 0
					post_text = post_text + 'Comment is too long for this version of the script.\n'
					continue
				# TODO Comment is too long
				if i.text is not None:
					post_text = post_text + f'{i.text}\n'
				if i.tail:
					i.tail = i.tail.strip('\n')
					i.tail = i.tail.strip()
					if i.tail:
						post_text = post_text + f'{i.tail}\n'
		return str(post_text), picture_path
	else:
		return None, None
def tcp_loop():
	tcp_loop_state = True
	# ------------------------------------------
	tcp_viewed = False
	while tcp_loop_state:
		# first iteration always produces empty byte string in non-blocking mode
		line = p.stdout.readline()
		if line != b'':
			visit_time_string = re.search(r'\d{4}-\d{2}-\d{2} \d{1,2}:\d{1,2}:\d{1,2}\.\d*',
										  line.decode('utf-8')).group(0)
			visit_time = datetime.datetime.strptime(visit_time_string, '%Y-%m-%d %H:%M:%S.%f')
			# visit_time_list = list(map(int,re.split(':', visit_time_string)))
			# visit_time = visit_time_list[0] * 3600 + visit_time_list[1] * 60 + visit_time_list[2]
			if not disable_time_start < visit_time < disable_time_end:
				if not tcp_viewed:
					print(visit_time_string)
				tcp_viewed = True
				# print(visit_time_string)
		else:
			tcp_loop_state = False
	return tcp_viewed
def send_notification(post_text, picture):
	if start_arg == 'notif':
		post_text = str(New_posts) + ' new posts'
		push = pb.push_note(data, post_text)
	elif start_arg == 'text_only':
		push = pb.push_note(data, post_text)
	elif start_arg == 'text_image':
		if picture is not None:
			with open(f'{picture}', "rb") as pic:
				file_data = pb.upload_file(pic, f'{picture[5:]}')
			push_picture = pb.push_file(**file_data)
			push = pb.push_note(data, post_text)
		else:
			push = pb.push_note(data, post_text)
delay_period_sec = 10
Message_period_sec = 60
link = "http://nowere.net/b"
file_name = "Data_Post_No.dat"
access_token = ""
command = """addr=$(host nowere.net | awk '/has address/ {print$4}');
addr="dst ""${addr}"" and (port 80 or port 443)";
tcpdump -i tun0 -tttt -nn "${addr}" -l """
start_arg = initial_arg()
try:
	file = open(file_name, 'r')
	Last_viewed = int(re.search(r'Last_viewed = (\d+)', file.readline()).group(1))
	Status = re.search(r'Status = "(down|up)"', file.readline()).group(1)
except Exception as e:
	with open(file_name, 'w') as file:
		file.write('Last_viewed = 0\nStatus = "down"\n')
	Last_viewed = 0
	Status = 'down'
pb = PushBullet(access_token)
data = 'Nowere'
text = ''
print('Last_viewed = ', Last_viewed)
print('Status = "' + Status + '"')
Last_reported = Max_No = Last_viewed
flag_reset_tcpdump = 0
pre_utc_dt = datetime.datetime.utcnow()
p = subprocess.Popen(command, shell=True, bufsize=-1, stdout=subprocess.PIPE)
os.set_blocking(p.stdout.fileno(), False)
start = time.time()
delay = chan_status_notified = 0
while True:
	# ------------------------------------------
	if time.time() > start + delay:
		disable_time_start = datetime.datetime.now()
		int_time_start = int(time.time())
		request_time = datetime.datetime.utcnow()  # debug
		try:
			f = urllib.request.urlopen(link)  # может иметь таймаут вплоть до 30 секунд, 10 не подойдёт, начнётся дос
			print(f'Request {request_time}')  # debug
		except HTTPError as e:
			# Error_flag = True
			Error_text = 'The server couldn\'t fulfill the request.\nError code: ' + str(e.code)
			Status = "down"
		except URLError as e:
			# Error_flag = True
			Error_text = 'We failed to reach a server.\nReason: ' + str(e.reason)
			Status = "down"
		else:
			site = f.read().decode('utf-8')
			# last_post = re.findall(r'<span .*<a .*No\.(\d+)</a>.*</span>', site)
			last_post = re.findall(r'<span class="reflink"> <a href=".{0,100}">No\.(\d+)</a>  </span>', site)
			Max_No = max(list(map(int, last_post)))
			Status = "up"
		if Status == 'up':
			picture_send = text_send = False
			post_text, picture = parse_post(Max_No, site)
			if picture is not None:
				picture_send = True
			if post_text is not None:
				text_send = True
			print("Max No ", Max_No)
		disable_time_end = datetime.datetime.now()
		int_time_end = int(time.time())
		delay += (int_time_end - int_time_start + delay_period_sec)
	tcp_viewed = tcp_loop()
	if tcp_viewed:
		if Last_viewed < Max_No:
			Last_viewed = Max_No
			with open(file_name, 'w') as file:
				file.write(f'Last_viewed = {Last_viewed}\nStatus = "{Status}"\n')
	if chan_status_notified == 1 and Status == 'up':
		chan_status_notified = 0
		print('chan is UP again!')
		text = 'chan is UP again!'
		push = pb.push_note(data, text)
	elif Status == 'down':
		# Send_Message('chan is DOWN!\n' + Error_text)
		if chan_status_notified == 0:
			print('chan is down!\n' + Error_text)
			text = 'chan is down!\n' + Error_text
			push = pb.push_note(data, text)
			chan_status_notified = 1
		continue
	if Last_viewed < Max_No:
		if Last_reported < Max_No:
			New_posts = Max_No - Last_viewed
			print(str(New_posts) + ' new posts')
			if text_send or picture_send:
				send_notification(post_text, picture)
			Last_reported = Max_No
		with open(file_name, 'w') as file:
			file.write(f'Last_viewed = {Last_viewed}\nStatus = "{Status}"\n')
	# ------------------------------------------
	utc_dt = datetime.datetime.utcnow()
	if (utc_dt.hour == 21) and (pre_utc_dt.hour == 20):
		p.terminate()
		p = subprocess.Popen(command, shell=True, bufsize=-1, stdout=subprocess.PIPE)
		os.set_blocking(p.stdout.fileno(), False)
		print('TCPDUMP reset')
		push = pb.push_note(data, 'TCPDUMP reset')
	pre_utc_dt = utc_dt
	time.sleep(0.5)
p.terminate()