import yaml from . import CHATFILE, TARGET, URL_HOSTNAME from pytgbot.bot.sync import SyncBot from pytgbot.api_types.sendable.inline import InlineQueryResultArticle, InputTextMessageContent from pytgbot.api_types.receivable.inline import InlineQuery from pytgbot.api_types.receivable.updates import Update from .states import CreatePostWorkflow from urllib.parse import urljoin #from . import solr,reindex from solrfet2020 import SolrFet2020 from . import fet, users from .users import User from io import BytesIO from key import API_KEY import requests from .workflows import AuthWorkflow import logging logger=logging.getLogger() from misc import SaveFileMapping, SaveFileObject from lxml.html.clean import clean_html, Cleaner solr=SolrFet2020() def TelegramIntegrationException(Exception): pass def get_chat_id(update): if update.message and update.message.chat: return update.message.chat.id if update.callback_query: return update.callback_query.message.chat.id def get_message_id(update): if update.message: return update.message.message_id def get_from_id(update): if update.message and update.message.to_array(): return str(update.message.to_array()["from"]["id"]) if update.callback_query and update.callback_query.to_array(): return str(update.callback_query.to_array()["from"]["id"]) def get_from(update): if update.message and update.message.to_array(): return (update.message.to_array()["from"]) if update.callback_query and update.callback_query.to_array(): return (update.callback_query.to_array()["from"]) def download_file(url): local_filename = url.split('/')[-1] # NOTE the stream=True parameter below with requests.get(url, stream=True) as r: r.raise_for_status() with open(local_filename, 'wb') as f: for chunk in r.iter_content(chunk_size=8192): # If you have chunk encoded response uncomment if # and set chunk_size parameter to None. #if chunk: f.write(chunk) return local_filename class BaseChat(SaveFileObject): "Basis für einen Telegram Chat" def __init__(self,id, bot): self.id=id #self.chat_id=chat_id self.bot=bot self.workflows={} self.last_message_id=None self.debug=False self.type="group" self.mode ="" def to_dict(self): return { "id": self.id, "workflows": self.workflows, "debug": self.debug, "type": self.type, "mode": self.mode } @classmethod def from_dict(self, bot, d): c=Chat(d["id"],bot) c.debug=d["debug"] c.type=d["type"] c.mode=d.get("mode","") return c def echo(self,update): self.reply_msg(yaml.dump(update._raw)+"\nfrom"+str(get_from_id(update))) def send_msg(self, text,**kwargs): self.bot.send_message(chat_id=self.id, text=text, **kwargs) def reply_msg(self, text, **kwargs): self.bot.send_message(chat_id=self.id, text=text, reply_to_message_id=self.last_message_id,**kwargs) def asdict(self): return self.to_dict() def inline(self,query): pass def process_update(self,update): if update.inline_query: return self.inline(update.inline_query) self.last_message_id=get_message_id(update) w=self.workflows.get(get_from_id(update),None) if w: self.workflows[get_from_id(update)]=w if w and w.is_finished: self.workflows[get_from_id(update)]=None w=None if self.debug: self.echo(update) if update.message and w: w.process_message(update.message.text) if update.callback_query: self.send_msg("processing callback %s" % str(w)) if w: w.process_message(update.callback_query.data) self.bot.edit_message_text( chat_id=update.callback_query.message.chat.id, message_id=update.callback_query.message.message_id, text=update.callback_query.message.text+": "+update.callback_query.data) if update.message and update.message.photo: ff=max(update.message.photo, key=lambda x: x.file_size) # Foto mit bester Auflösung fff = self.bot.get_file(ff.file_id) url=fff.get_download_url(API_KEY) r = requests.get(url) fn = url.split('/')[-1] media=(fn, BytesIO(r.content),r.headers["content-type"]) if w: w.process_message(update.message.text, media=media) if update.message and update.message.chat: self.type=update.message.chat.type u=users[update] users.to_file() class Chat(BaseChat): def inline(self, query): #r=solr.search("text_txt: %s" % ,sort="date_dt desc").docs links,hits=solr.search(query.query) r= links[0:6] res=[ InlineQueryResultArticle( id=d["url"], title=d["title"], url=urljoin(TARGET,d["url"]), thumb_url = urljoin(TARGET,d["image"]), input_message_content = InputTextMessageContent(message_text=urljoin(TARGET,d["url"])) ) for d in r] #links=[p["title"]+": "+"(%s) "% p["public_date"] + urljoin(TARGET,p["url"]) for p in r] self.bot.answer_inline_query(inline_query_id=query.id,results=res ) return def process_command(self,cmd,txt,update): self.last_message_id=get_message_id(update) u=users[update] # print("--\ndict: %s" % str(users.asdict())) #users[get_from_id(update)]=u if cmd == "/s" or cmd =="/search": self.reply_msg("searching ...") links,hits=solr.search(txt) for d in links: self.send_msg(str(d["text"]), parse_mode="html") if hits==0: self.send_msg("Nichts gefunden sorry.") return True elif cmd =="/mode": self.mode=txt self.reply_msg("Mode: %s" % txt) return True elif cmd == "/debug": if not u.fet_user: self.reply_msg("bitte vorher /auth ausführen wenn du ein FET Mitglied bist") return True if self.debug: self.debug = False else: self.debug = True #not self.debug self.reply_msg("Debug: %s" % str(self.debug)) return True elif cmd =="/post": if not u.fet_user: self.reply_msg("bitte vorher /auth ausführen wenn du ein FET Mitglied bist") return True self.workflows[get_from_id(update)]=CreatePostWorkflow(chat=self) return True elif cmd == "/reindex": if not u.fet_user: self.reply_msg("bitte vorher /auth ausführen wenn du ein FET Mitglied bist") return True self.reply_msg("Das kann ein bissl dauern...") solr.reindex() self.send_msg("Fertig mit dem neuen Index") return True elif cmd == "/auth": if u.fet_user: self.reply_msg("Du bist schon authentifiziert...") else: u.token="afwerve" u.a=1 self.reply_msg(urljoin("https://"+URL_HOSTNAME, "/auth/%s/%s" %(u.id, u.token))) self.send_msg(urljoin("https://",URL_HOSTNAME)) users.to_file() return True else: return False return False def get_command_from_update(update): "get the command and the text if there is one" if update.message and update.message.entities and update.message.entities[0].type=="bot_command": return update.message.text[update.message.entities[0].offset:update.message.entities[0].offset+update.message.entities[0].length], \ update.message.text[update.message.entities[0].offset+update.message.entities[0].length:].strip() return None, None class ChatManager(SaveFileMapping): def __init__(self,bot): super().__init__(file=CHATFILE) if not type(bot) is SyncBot: raise TelegramIntegrationException("This ChatManager needs a SyncBot from pytgbot as an argument") self.bot=bot self.from_file() def __getitem__(self,key): if type(key) is Update: return self.__getitem__(get_chat_id(key)) c=super().__getitem__(key) if not c: c=Chat(id=key,bot=self.bot) self[key]=c return c def from_dict(self,dd): if type(dd) is dict: self.data={dd[d]["id"]: Chat.from_dict(self.bot,dd[d]) for d in dd} elif dd is not None: raise AttributeError("from_dict needs a dict got %s" % str(type(dd))) def send(self, chat_id=None, text=None): if int(chat_id) in self.chats: self.chats[int(chat_id)].send_msg(text) else: logger.debug(yaml.dump(self.chats)) def process_update(self,update): chat=self[update] cmd, txt = get_command_from_update(update) if cmd: if not chat.process_command(cmd,txt,update): chat.reply_msg("Wrong command %s" % cmd) else: chat.process_update(update) self.to_file()