cimport lib cimport str cimport post cimport bridge import sys sys.path.append('./py') cdef int log_info(char *message) except -1: return lib.log_info('%s', message) cdef int log_warn(char *message) except -1: return lib.log_warn('%s', message) cdef int log_error(char *message) except -1: return lib.log_error('%s', message) cdef int log_debug(char *message) except -1: return lib.log_debug('%s', message) def encode_str(str): return str.encode('UTF-8') def decode_str(str): return str.decode('UTF-8') class OutputHook(object): def __init__(self): self.fd = sys.__stdout__ def __getattr__(self, attr): return getattr(self.fd, attr) def write(self, message): if len(message) > 0 and message != '\n': log_info(encode_str(message)) hook = OutputHook() sys.stdout = hook sys.stderr = hook import log class PortalLogger(log.Logger): def debug(self, message): log_debug(encode_str(message)) def info(self, message): log_info(encode_str(message)) def warn(self, message): log_warn(encode_str(message)) def error(self, message): log_error(encode_str(message)) log.set_logger(PortalLogger()) def exception_handler(exception_type, exception, traceback): log.error(repr(exception)) sys.excepthook = exception_handler from random import randrange class Portal(): def __init__(self, modules): self.modules = modules self.searches = {} def print_modules(self): for name in ALL_MODULES.keys(): log.info(f'Registered module \'{name}\'.') def new_id(self): while True: id = randrange(16 ** 5) if id not in self.searches: return id def search(self, module, query): if module not in self.modules: return -1 mod = self.modules[module] search = mod[0].search(query, *mod[1]) if not search: return -1 id = self.new_id() self.searches[id] = search return id def get_page(self, id, num): if id not in self.searches: return None try: return self.searches[id].get_page(num) except Exception as e: log.error(repr(e)) return None def get_item(self, id, unique_id): if id not in self.searches: return None try: return self.searches[id].module.get_item(unique_id) except Exception as e: log.error(repr(e)) return None from modules import ALL_MODULES portal = Portal(ALL_MODULES) portal.print_modules() from post import PostType, DateType cdef public int portal_bridge_search(str.str *module, str.str *query) except -1: cdef char *c_str0 = str.al_str_to_c_str(module) cdef char *c_str1 = str.al_str_to_c_str(query) ret = portal.search(decode_str(c_str0), decode_str(c_str1)) lib.al_free(c_str0) lib.al_free(c_str1) return ret cdef int py_str_to_str(str.str *s, char *py_c_str) except -1: str.al_str_from(s, py_c_str) return 0 cdef int py_str_to_wstr(str.wstr *w, char *py_c_str) except -1: str.al_wstr_from_cstr(w, py_c_str) return 0 cdef int add_post_internal(bridge.camu_search *search, int id, unsigned int num, char *py_unique_id) except -1: cdef post.camu_post cpost cdef str.str key cdef str.str url cdef str.str ext cdef str.str thumbnail_url cdef str.str thumbnail_ext py_post = portal.get_item(id, decode_str(py_unique_id)) if not py_post: return 0 post.camu_post_reset(&cpost) cpost.version = py_post.version cpost.type = py_post.type.value py_str_to_str(&cpost.unique_id, encode_str(py_post.unique_id)) if cpost.type == PostType.TOMBSTONE.value: bridge.camu_search_add_post(search, num, &cpost) return 0 py_str_to_str(&cpost.url, encode_str(py_post.url)) for date in py_post.dates: post.camu_post_add_date(&cpost, date.type, date.range[0], date.range[1], date.meta) py_str_to_str(&cpost.author.unique_id, encode_str(py_post.author.unique_id)) py_str_to_wstr(&cpost.author.username, encode_str(py_post.author.username)) py_str_to_wstr(&cpost.author.display_name, encode_str(py_post.author.display_name)) py_str_to_str(&cpost.author.profile_picture_url, encode_str(py_post.author.profile_picture_url.url)) if cpost.type != PostType.REPOST.value: py_str_to_wstr(&cpost.title, encode_str(py_post.title)) py_str_to_wstr(&cpost.text, encode_str(py_post.text)) cpost.likes.set = py_post.likes != None if cpost.likes.set: cpost.likes.i = py_post.likes cpost.bookmarks.set = py_post.bookmarks != None if cpost.bookmarks.set: cpost.bookmarks.i = py_post.bookmarks cpost.reposts.set = py_post.reposts != None if cpost.reposts.set: cpost.reposts.i = py_post.reposts cpost.quotes.set = py_post.quotes != None if cpost.quotes.set: cpost.quotes.i = py_post.quotes cpost.comments.set = py_post.comments != None if cpost.comments.set: cpost.comments.i = py_post.comments cpost.views.set = py_post.views != None if cpost.views.set: cpost.views.i = py_post.views for k, media in py_post.media.items(): py_str_to_str(&key, encode_str(k)) py_str_to_str(&url, encode_str(media.url.url)) py_str_to_str(&ext, encode_str(media.url.ext)) py_str_to_str(&thumbnail_url, encode_str(media.thumbnail_url.url)) py_str_to_str(&thumbnail_ext, encode_str(media.thumbnail_url.ext)) post.camu_post_add_media(&cpost, media.type.value, &key, &url, &ext, &thumbnail_url, &thumbnail_ext) py_str_to_str(&cpost.post.unique_id, encode_str(py_post.post.unique_id)) py_str_to_str(&cpost.quoted.unique_id, encode_str(py_post.quoted.unique_id)) py_str_to_str(&cpost.in_reply_to.unique_id, encode_str(py_post.in_reply_to.unique_id)) if py_post.post.unique_id: add_post_internal(search, id, num, encode_str(py_post.post.unique_id)) if py_post.quoted.unique_id: add_post_internal(search, id, num, encode_str(py_post.quoted.unique_id)) bridge.camu_search_add_post(search, num, &cpost) return 0 cdef public int portal_bridge_get_page(bridge.camu_search *search, int id, unsigned int num) except -1: page = portal.get_page(id, num) if not page: return -1 cdef str.str unique_id for py_unique_id in page: py_str_to_str(&unique_id, encode_str(py_unique_id)) bridge.camu_search_add_to_list(search, num, &unique_id) add_post_internal(search, id, num, encode_str(py_unique_id)) return 0