| 
									
										
										
										
											2024-03-02 17:06:58 +00:00
										 |  |  | __filename__ = "daemon_get_hashtag.py" | 
					
						
							|  |  |  | __author__ = "Bob Mottram" | 
					
						
							|  |  |  | __license__ = "AGPL3+" | 
					
						
							| 
									
										
										
										
											2024-12-22 23:37:30 +00:00
										 |  |  | __version__ = "1.6.0" | 
					
						
							| 
									
										
										
										
											2024-03-02 17:06:58 +00:00
										 |  |  | __maintainer__ = "Bob Mottram" | 
					
						
							|  |  |  | __email__ = "bob@libreserver.org" | 
					
						
							|  |  |  | __status__ = "Production" | 
					
						
							| 
									
										
										
										
											2024-12-25 14:31:14 +00:00
										 |  |  | __module_group__ = "Daemon GET" | 
					
						
							| 
									
										
										
										
											2024-03-02 17:06:58 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | import json | 
					
						
							|  |  |  | import urllib.parse | 
					
						
							| 
									
										
										
										
											2024-03-02 17:24:29 +00:00
										 |  |  | from session import establish_session | 
					
						
							| 
									
										
										
										
											2024-03-02 17:06:58 +00:00
										 |  |  | from httpcodes import http_400 | 
					
						
							| 
									
										
										
										
											2024-03-02 17:24:29 +00:00
										 |  |  | from httpcodes import http_404 | 
					
						
							| 
									
										
										
										
											2024-03-02 17:06:58 +00:00
										 |  |  | from httpcodes import write2 | 
					
						
							|  |  |  | from httpheaders import login_headers | 
					
						
							|  |  |  | from httpheaders import redirect_headers | 
					
						
							|  |  |  | from httpheaders import set_headers | 
					
						
							|  |  |  | from blocking import is_blocked_hashtag | 
					
						
							|  |  |  | from utils import convert_domains | 
					
						
							|  |  |  | from utils import get_nickname_from_actor | 
					
						
							| 
									
										
										
										
											2024-03-02 17:24:29 +00:00
										 |  |  | from fitnessFunctions import fitness_performance | 
					
						
							| 
									
										
										
										
											2024-03-02 17:06:58 +00:00
										 |  |  | from webapp_utils import html_hashtag_blocked | 
					
						
							|  |  |  | from webapp_search import html_hashtag_search | 
					
						
							|  |  |  | from webapp_search import hashtag_search_rss | 
					
						
							|  |  |  | from webapp_search import hashtag_search_json | 
					
						
							| 
									
										
										
										
											2024-03-02 17:24:29 +00:00
										 |  |  | from webapp_hashtagswarm import get_hashtag_categories_feed | 
					
						
							| 
									
										
										
										
											2024-03-02 17:06:58 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | def hashtag_search_rss2(self, calling_domain: str, | 
					
						
							|  |  |  |                         path: str, cookie: str, | 
					
						
							|  |  |  |                         base_dir: str, http_prefix: str, | 
					
						
							|  |  |  |                         domain: str, domain_full: str, port: int, | 
					
						
							|  |  |  |                         onion_domain: str, i2p_domain: str, | 
					
						
							| 
									
										
										
										
											2024-04-11 10:00:00 +00:00
										 |  |  |                         getreq_start_time, | 
					
						
							|  |  |  |                         system_language: str, | 
					
						
							|  |  |  |                         fitness: {}, debug: bool) -> None: | 
					
						
							| 
									
										
										
										
											2024-03-02 17:06:58 +00:00
										 |  |  |     """Return an RSS 2 feed for a hashtag
 | 
					
						
							|  |  |  |     """
 | 
					
						
							|  |  |  |     hashtag = path.split('/tags/rss2/')[1] | 
					
						
							|  |  |  |     if is_blocked_hashtag(base_dir, hashtag): | 
					
						
							|  |  |  |         http_400(self) | 
					
						
							|  |  |  |         return | 
					
						
							|  |  |  |     nickname = None | 
					
						
							|  |  |  |     if '/users/' in path: | 
					
						
							|  |  |  |         actor = \ | 
					
						
							|  |  |  |             http_prefix + '://' + domain_full + path | 
					
						
							|  |  |  |         nickname = \ | 
					
						
							|  |  |  |             get_nickname_from_actor(actor) | 
					
						
							|  |  |  |     hashtag_str = \ | 
					
						
							|  |  |  |         hashtag_search_rss(nickname, | 
					
						
							|  |  |  |                            domain, port, | 
					
						
							|  |  |  |                            base_dir, hashtag, | 
					
						
							|  |  |  |                            http_prefix, | 
					
						
							| 
									
										
										
										
											2024-04-11 10:00:00 +00:00
										 |  |  |                            system_language) | 
					
						
							| 
									
										
										
										
											2024-03-02 17:06:58 +00:00
										 |  |  |     if hashtag_str: | 
					
						
							|  |  |  |         msg = hashtag_str.encode('utf-8') | 
					
						
							|  |  |  |         msglen = len(msg) | 
					
						
							|  |  |  |         set_headers(self, 'text/xml', msglen, | 
					
						
							|  |  |  |                     cookie, calling_domain, False) | 
					
						
							|  |  |  |         write2(self, msg) | 
					
						
							|  |  |  |     else: | 
					
						
							|  |  |  |         origin_path_str = path.split('/tags/rss2/')[0] | 
					
						
							|  |  |  |         origin_path_str_absolute = \ | 
					
						
							|  |  |  |             http_prefix + '://' + domain_full + origin_path_str | 
					
						
							|  |  |  |         if calling_domain.endswith('.onion') and onion_domain: | 
					
						
							|  |  |  |             origin_path_str_absolute = \ | 
					
						
							|  |  |  |                 'http://' + onion_domain + origin_path_str | 
					
						
							|  |  |  |         elif (calling_domain.endswith('.i2p') and onion_domain): | 
					
						
							|  |  |  |             origin_path_str_absolute = \ | 
					
						
							|  |  |  |                 'http://' + i2p_domain + origin_path_str | 
					
						
							|  |  |  |         redirect_headers(self, origin_path_str_absolute + '/search', | 
					
						
							| 
									
										
										
										
											2024-04-16 13:47:21 +00:00
										 |  |  |                          cookie, calling_domain, 303) | 
					
						
							| 
									
										
										
										
											2024-04-11 10:00:00 +00:00
										 |  |  |     fitness_performance(getreq_start_time, fitness, | 
					
						
							| 
									
										
										
										
											2024-03-02 17:06:58 +00:00
										 |  |  |                         '_GET', '_hashtag_search_rss2', | 
					
						
							| 
									
										
										
										
											2024-04-11 10:00:00 +00:00
										 |  |  |                         debug) | 
					
						
							| 
									
										
										
										
											2024-03-02 17:06:58 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | def hashtag_search_json2(self, calling_domain: str, | 
					
						
							|  |  |  |                          referer_domain: str, | 
					
						
							|  |  |  |                          path: str, cookie: str, | 
					
						
							|  |  |  |                          base_dir: str, http_prefix: str, | 
					
						
							|  |  |  |                          domain: str, domain_full: str, port: int, | 
					
						
							|  |  |  |                          onion_domain: str, i2p_domain: str, | 
					
						
							|  |  |  |                          getreq_start_time, | 
					
						
							| 
									
										
										
										
											2024-04-11 10:00:00 +00:00
										 |  |  |                          max_posts_in_feed: int, | 
					
						
							|  |  |  |                          fitness: {}, debug: bool) -> None: | 
					
						
							| 
									
										
										
										
											2024-03-02 17:06:58 +00:00
										 |  |  |     """Return a json collection for a hashtag
 | 
					
						
							|  |  |  |     """
 | 
					
						
							|  |  |  |     page_number = 1 | 
					
						
							|  |  |  |     if '?page=' in path: | 
					
						
							|  |  |  |         page_number_str = path.split('?page=')[1] | 
					
						
							|  |  |  |         if page_number_str.isdigit(): | 
					
						
							|  |  |  |             page_number = int(page_number_str) | 
					
						
							|  |  |  |         path = path.split('?page=')[0] | 
					
						
							|  |  |  |     hashtag = path.split('/tags/')[1] | 
					
						
							|  |  |  |     if is_blocked_hashtag(base_dir, hashtag): | 
					
						
							|  |  |  |         http_400(self) | 
					
						
							|  |  |  |         return | 
					
						
							|  |  |  |     nickname = None | 
					
						
							|  |  |  |     if '/users/' in path: | 
					
						
							|  |  |  |         actor = \ | 
					
						
							|  |  |  |             http_prefix + '://' + domain_full + path | 
					
						
							|  |  |  |         nickname = \ | 
					
						
							|  |  |  |             get_nickname_from_actor(actor) | 
					
						
							|  |  |  |     hashtag_json = \ | 
					
						
							|  |  |  |         hashtag_search_json(nickname, | 
					
						
							|  |  |  |                             domain, port, | 
					
						
							|  |  |  |                             base_dir, hashtag, | 
					
						
							|  |  |  |                             page_number, max_posts_in_feed, | 
					
						
							|  |  |  |                             http_prefix) | 
					
						
							|  |  |  |     if hashtag_json: | 
					
						
							|  |  |  |         msg_str = json.dumps(hashtag_json) | 
					
						
							|  |  |  |         msg_str = convert_domains(calling_domain, referer_domain, | 
					
						
							|  |  |  |                                   msg_str, http_prefix, domain, | 
					
						
							|  |  |  |                                   onion_domain, i2p_domain) | 
					
						
							|  |  |  |         msg = msg_str.encode('utf-8') | 
					
						
							|  |  |  |         msglen = len(msg) | 
					
						
							|  |  |  |         set_headers(self, 'application/json', msglen, | 
					
						
							|  |  |  |                     None, calling_domain, True) | 
					
						
							|  |  |  |         write2(self, msg) | 
					
						
							|  |  |  |     else: | 
					
						
							|  |  |  |         origin_path_str = path.split('/tags/')[0] | 
					
						
							|  |  |  |         origin_path_str_absolute = \ | 
					
						
							|  |  |  |             http_prefix + '://' + domain_full + origin_path_str | 
					
						
							|  |  |  |         if calling_domain.endswith('.onion') and onion_domain: | 
					
						
							|  |  |  |             origin_path_str_absolute = \ | 
					
						
							|  |  |  |                 'http://' + onion_domain + origin_path_str | 
					
						
							|  |  |  |         elif (calling_domain.endswith('.i2p') and onion_domain): | 
					
						
							|  |  |  |             origin_path_str_absolute = \ | 
					
						
							|  |  |  |                 'http://' + i2p_domain + origin_path_str | 
					
						
							|  |  |  |         redirect_headers(self, origin_path_str_absolute, | 
					
						
							| 
									
										
										
										
											2024-04-16 13:47:21 +00:00
										 |  |  |                          cookie, calling_domain, 303) | 
					
						
							| 
									
										
										
										
											2024-04-11 10:00:00 +00:00
										 |  |  |     fitness_performance(getreq_start_time, fitness, | 
					
						
							| 
									
										
										
										
											2024-03-02 17:06:58 +00:00
										 |  |  |                         '_GET', '_hashtag_search_json', | 
					
						
							| 
									
										
										
										
											2024-04-11 10:00:00 +00:00
										 |  |  |                         debug) | 
					
						
							| 
									
										
										
										
											2024-03-02 17:06:58 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | def hashtag_search2(self, calling_domain: str, | 
					
						
							|  |  |  |                     path: str, cookie: str, | 
					
						
							|  |  |  |                     base_dir: str, http_prefix: str, | 
					
						
							|  |  |  |                     domain: str, domain_full: str, port: int, | 
					
						
							|  |  |  |                     onion_domain: str, i2p_domain: str, | 
					
						
							|  |  |  |                     getreq_start_time, | 
					
						
							|  |  |  |                     curr_session, | 
					
						
							| 
									
										
										
										
											2024-04-11 10:00:00 +00:00
										 |  |  |                     max_posts_in_hashtag_feed: int, | 
					
						
							|  |  |  |                     translate: {}, account_timezone: {}, | 
					
						
							|  |  |  |                     bold_reading_nicknames: {}, | 
					
						
							|  |  |  |                     fitness: {}, debug: bool, | 
					
						
							|  |  |  |                     recent_posts_cache: {}, | 
					
						
							|  |  |  |                     max_recent_posts: int, | 
					
						
							|  |  |  |                     cached_webfingers: {}, | 
					
						
							|  |  |  |                     person_cache: {}, | 
					
						
							|  |  |  |                     project_version: str, | 
					
						
							|  |  |  |                     yt_replace_domain: str, | 
					
						
							|  |  |  |                     twitter_replacement_domain: str, | 
					
						
							|  |  |  |                     show_published_date_only: bool, | 
					
						
							|  |  |  |                     peertube_instances: [], | 
					
						
							|  |  |  |                     allow_local_network_access: bool, | 
					
						
							|  |  |  |                     theme_name: str, | 
					
						
							|  |  |  |                     system_language: str, | 
					
						
							|  |  |  |                     max_like_count: int, | 
					
						
							|  |  |  |                     signing_priv_key_pem: str, | 
					
						
							|  |  |  |                     cw_lists: {}, | 
					
						
							|  |  |  |                     lists_enabled: {}, | 
					
						
							|  |  |  |                     dogwhistles: {}, | 
					
						
							|  |  |  |                     map_format: str, | 
					
						
							|  |  |  |                     access_keys: {}, | 
					
						
							|  |  |  |                     min_images_for_accounts: [], | 
					
						
							|  |  |  |                     buy_sites: [], | 
					
						
							| 
									
										
										
										
											2024-11-03 22:11:41 +00:00
										 |  |  |                     auto_cw_cache: {}, | 
					
						
							| 
									
										
										
										
											2024-12-17 13:50:48 +00:00
										 |  |  |                     ua_str: str, | 
					
						
							| 
									
										
										
										
											2025-01-20 17:55:29 +00:00
										 |  |  |                     mitm_servers: [], | 
					
						
							|  |  |  |                     instance_software: {}) -> None: | 
					
						
							| 
									
										
										
										
											2024-03-02 17:06:58 +00:00
										 |  |  |     """Return the result of a hashtag search
 | 
					
						
							|  |  |  |     """
 | 
					
						
							|  |  |  |     page_number = 1 | 
					
						
							|  |  |  |     if '?page=' in path: | 
					
						
							|  |  |  |         page_number_str = path.split('?page=')[1] | 
					
						
							|  |  |  |         if '#' in page_number_str: | 
					
						
							|  |  |  |             page_number_str = page_number_str.split('#')[0] | 
					
						
							|  |  |  |         if len(page_number_str) > 5: | 
					
						
							|  |  |  |             page_number_str = "1" | 
					
						
							|  |  |  |         if page_number_str.isdigit(): | 
					
						
							|  |  |  |             page_number = int(page_number_str) | 
					
						
							|  |  |  |     hashtag = path.split('/tags/')[1] | 
					
						
							|  |  |  |     if '?page=' in hashtag: | 
					
						
							|  |  |  |         hashtag = hashtag.split('?page=')[0] | 
					
						
							|  |  |  |     hashtag = urllib.parse.unquote_plus(hashtag) | 
					
						
							|  |  |  |     if is_blocked_hashtag(base_dir, hashtag): | 
					
						
							|  |  |  |         print('BLOCK: blocked hashtag #' + hashtag) | 
					
						
							|  |  |  |         msg = html_hashtag_blocked(base_dir, | 
					
						
							| 
									
										
										
										
											2024-04-11 10:00:00 +00:00
										 |  |  |                                    translate).encode('utf-8') | 
					
						
							| 
									
										
										
										
											2024-03-02 17:06:58 +00:00
										 |  |  |         msglen = len(msg) | 
					
						
							|  |  |  |         login_headers(self, 'text/html', msglen, calling_domain) | 
					
						
							|  |  |  |         write2(self, msg) | 
					
						
							|  |  |  |         return | 
					
						
							|  |  |  |     nickname = None | 
					
						
							|  |  |  |     if '/users/' in path: | 
					
						
							|  |  |  |         nickname = path.split('/users/')[1] | 
					
						
							|  |  |  |         if '/' in nickname: | 
					
						
							|  |  |  |             nickname = nickname.split('/')[0] | 
					
						
							|  |  |  |         if '?' in nickname: | 
					
						
							|  |  |  |             nickname = nickname.split('?')[0] | 
					
						
							|  |  |  |     timezone = None | 
					
						
							| 
									
										
										
										
											2024-04-11 10:00:00 +00:00
										 |  |  |     if account_timezone.get(nickname): | 
					
						
							|  |  |  |         timezone = account_timezone.get(nickname) | 
					
						
							| 
									
										
										
										
											2024-03-02 17:06:58 +00:00
										 |  |  |     bold_reading = False | 
					
						
							| 
									
										
										
										
											2024-04-11 10:00:00 +00:00
										 |  |  |     if bold_reading_nicknames.get(nickname): | 
					
						
							| 
									
										
										
										
											2024-03-02 17:06:58 +00:00
										 |  |  |         bold_reading = True | 
					
						
							|  |  |  |     hashtag_str = \ | 
					
						
							|  |  |  |         html_hashtag_search(nickname, domain, port, | 
					
						
							| 
									
										
										
										
											2024-04-11 10:00:00 +00:00
										 |  |  |                             recent_posts_cache, | 
					
						
							|  |  |  |                             max_recent_posts, | 
					
						
							|  |  |  |                             translate, | 
					
						
							| 
									
										
										
										
											2024-03-02 17:06:58 +00:00
										 |  |  |                             base_dir, hashtag, page_number, | 
					
						
							|  |  |  |                             max_posts_in_hashtag_feed, | 
					
						
							|  |  |  |                             curr_session, | 
					
						
							| 
									
										
										
										
											2024-04-11 10:00:00 +00:00
										 |  |  |                             cached_webfingers, | 
					
						
							|  |  |  |                             person_cache, | 
					
						
							| 
									
										
										
										
											2024-03-02 17:06:58 +00:00
										 |  |  |                             http_prefix, | 
					
						
							| 
									
										
										
										
											2024-04-11 10:00:00 +00:00
										 |  |  |                             project_version, | 
					
						
							|  |  |  |                             yt_replace_domain, | 
					
						
							|  |  |  |                             twitter_replacement_domain, | 
					
						
							|  |  |  |                             show_published_date_only, | 
					
						
							|  |  |  |                             peertube_instances, | 
					
						
							|  |  |  |                             allow_local_network_access, | 
					
						
							|  |  |  |                             theme_name, | 
					
						
							|  |  |  |                             system_language, | 
					
						
							|  |  |  |                             max_like_count, | 
					
						
							|  |  |  |                             signing_priv_key_pem, | 
					
						
							|  |  |  |                             cw_lists, | 
					
						
							|  |  |  |                             lists_enabled, | 
					
						
							| 
									
										
										
										
											2024-03-02 17:06:58 +00:00
										 |  |  |                             timezone, bold_reading, | 
					
						
							| 
									
										
										
										
											2024-04-11 10:00:00 +00:00
										 |  |  |                             dogwhistles, | 
					
						
							|  |  |  |                             map_format, | 
					
						
							|  |  |  |                             access_keys, | 
					
						
							| 
									
										
										
										
											2024-03-02 17:06:58 +00:00
										 |  |  |                             'search', | 
					
						
							| 
									
										
										
										
											2024-04-11 10:00:00 +00:00
										 |  |  |                             min_images_for_accounts, | 
					
						
							|  |  |  |                             buy_sites, | 
					
						
							| 
									
										
										
										
											2024-12-17 13:50:48 +00:00
										 |  |  |                             auto_cw_cache, ua_str, | 
					
						
							| 
									
										
										
										
											2025-01-20 17:55:29 +00:00
										 |  |  |                             mitm_servers, | 
					
						
							|  |  |  |                             instance_software) | 
					
						
							| 
									
										
										
										
											2024-03-02 17:06:58 +00:00
										 |  |  |     if hashtag_str: | 
					
						
							|  |  |  |         msg = hashtag_str.encode('utf-8') | 
					
						
							|  |  |  |         msglen = len(msg) | 
					
						
							|  |  |  |         set_headers(self, 'text/html', msglen, | 
					
						
							|  |  |  |                     cookie, calling_domain, False) | 
					
						
							|  |  |  |         write2(self, msg) | 
					
						
							|  |  |  |     else: | 
					
						
							|  |  |  |         origin_path_str = path.split('/tags/')[0] | 
					
						
							|  |  |  |         origin_path_str_absolute = \ | 
					
						
							|  |  |  |             http_prefix + '://' + domain_full + origin_path_str | 
					
						
							|  |  |  |         if calling_domain.endswith('.onion') and onion_domain: | 
					
						
							|  |  |  |             origin_path_str_absolute = \ | 
					
						
							|  |  |  |                 'http://' + onion_domain + origin_path_str | 
					
						
							|  |  |  |         elif (calling_domain.endswith('.i2p') and onion_domain): | 
					
						
							|  |  |  |             origin_path_str_absolute = \ | 
					
						
							|  |  |  |                 'http://' + i2p_domain + origin_path_str | 
					
						
							|  |  |  |         redirect_headers(self, origin_path_str_absolute + '/search', | 
					
						
							| 
									
										
										
										
											2024-04-16 13:47:21 +00:00
										 |  |  |                          cookie, calling_domain, 303) | 
					
						
							| 
									
										
										
										
											2024-04-11 10:00:00 +00:00
										 |  |  |     fitness_performance(getreq_start_time, fitness, | 
					
						
							|  |  |  |                         '_GET', '_hashtag_search', debug) | 
					
						
							| 
									
										
										
										
											2024-03-02 17:24:29 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | def get_hashtag_categories_feed2(self, calling_domain: str, path: str, | 
					
						
							|  |  |  |                                  base_dir: str, proxy_type: str, | 
					
						
							|  |  |  |                                  getreq_start_time, | 
					
						
							|  |  |  |                                  debug: bool, | 
					
						
							| 
									
										
										
										
											2024-04-23 12:24:13 +00:00
										 |  |  |                                  curr_session, fitness: {}) -> None: | 
					
						
							| 
									
										
										
										
											2024-03-02 17:24:29 +00:00
										 |  |  |     """Returns the hashtag categories feed
 | 
					
						
							|  |  |  |     """
 | 
					
						
							|  |  |  |     curr_session = \ | 
					
						
							|  |  |  |         establish_session("get_hashtag_categories_feed", | 
					
						
							|  |  |  |                           curr_session, proxy_type, | 
					
						
							|  |  |  |                           self.server) | 
					
						
							|  |  |  |     if not curr_session: | 
					
						
							|  |  |  |         http_404(self, 27) | 
					
						
							|  |  |  |         return | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     hashtag_categories = None | 
					
						
							|  |  |  |     msg = \ | 
					
						
							|  |  |  |         get_hashtag_categories_feed(base_dir, hashtag_categories) | 
					
						
							|  |  |  |     if msg: | 
					
						
							|  |  |  |         msg = msg.encode('utf-8') | 
					
						
							|  |  |  |         msglen = len(msg) | 
					
						
							|  |  |  |         set_headers(self, 'text/xml', msglen, | 
					
						
							|  |  |  |                     None, calling_domain, True) | 
					
						
							|  |  |  |         write2(self, msg) | 
					
						
							|  |  |  |         if debug: | 
					
						
							|  |  |  |             print('Sent rss2 categories feed: ' + | 
					
						
							|  |  |  |                   path + ' ' + calling_domain) | 
					
						
							| 
									
										
										
										
											2024-04-23 12:24:13 +00:00
										 |  |  |         fitness_performance(getreq_start_time, fitness, | 
					
						
							| 
									
										
										
										
											2024-03-02 17:24:29 +00:00
										 |  |  |                             '_GET', '_get_hashtag_categories_feed', debug) | 
					
						
							|  |  |  |         return | 
					
						
							|  |  |  |     if debug: | 
					
						
							|  |  |  |         print('Failed to get rss2 categories feed: ' + | 
					
						
							|  |  |  |               path + ' ' + calling_domain) | 
					
						
							|  |  |  |     http_404(self, 28) |