From 58be5c779a6ecce34f382f5503d69fa591e32907 Mon Sep 17 00:00:00 2001 From: www Date: Mon, 26 Oct 2020 20:30:12 +0000 Subject: [PATCH] init --- .gitignore | 5 ++ bot.py | 82 +++++++++++++++++++++++++ bot/__init__.py | 0 bot/states.py | 113 +++++++++++++++++++++++++++++++++++ bot1/__init__.py | 1 + bot1/chats.py | 10 ++++ bot1/states.py | 128 ++++++++++++++++++++++++++++++++++++++++ docker-compose.yml | 13 ++++ fet2020api/__init__.py | 38 ++++++++++++ fet2020api/djangoapi.py | 76 ++++++++++++++++++++++++ solr.py | 14 +++++ spacytest.py | 20 +++++++ test.py | 74 +++++++++++++++++++++++ test2.py | 99 +++++++++++++++++++++++++++++++ 14 files changed, 673 insertions(+) create mode 100644 .gitignore create mode 100644 bot.py create mode 100644 bot/__init__.py create mode 100644 bot/states.py create mode 100644 bot1/__init__.py create mode 100644 bot1/chats.py create mode 100644 bot1/states.py create mode 100644 docker-compose.yml create mode 100644 fet2020api/__init__.py create mode 100644 fet2020api/djangoapi.py create mode 100644 solr.py create mode 100644 spacytest.py create mode 100644 test.py create mode 100644 test2.py diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..a566c97 --- /dev/null +++ b/.gitignore @@ -0,0 +1,5 @@ +*.jpg +.env/* +__pycache__ +*~ +key.py \ No newline at end of file diff --git a/bot.py b/bot.py new file mode 100644 index 0000000..2b696e7 --- /dev/null +++ b/bot.py @@ -0,0 +1,82 @@ +import logging + +from telegram.ext import CommandHandler, CallbackQueryHandler +from telegram.ext import Updater +from telegram import InlineKeyboardButton,InlineKeyboardMarkup +from telegram.ext import MessageHandler, Filters +from key import API_KEY +from bot.states import CreatePostWorkflow +from flask import Flask +app = Flask(__name__) + +@app.route('/') +def hello_world(): + return 'Hello, World!' + +# Bot Updater that will poll +updater = Updater(token=API_KEY, use_context=True) +# The Dispatcher that get all the Handlers +dispatcher = updater.dispatcher +logger = logging.getLogger() +logger.setLevel(logging.INFO) +ch = logging.StreamHandler() +ch.setLevel(logging.DEBUG) +logger.addHandler(ch) + +workflows = {} + +logger.info('initializing') +def start(update, context): + workflows[update.effective_chat.id]=CreatePostWorkflow(chat_id=update.effective_chat.id,context=context) + logger.info("Start") + context.bot.send_message(chat_id=update.effective_chat.id, text=update.message.text) + +start_handler = CommandHandler('start', start) +dispatcher.add_handler(start_handler) + +def test(update, context): + # workflows[update.effective_chat.id]=CreatePostWorkflow(chat_id=update.effective_chat.id,context=context) + logger.info("Test") + keyboard = [[InlineKeyboardButton("Option 1", callback_data='1'), + InlineKeyboardButton("Option 2", callback_data='2')], + [InlineKeyboardButton("Option 3", callback_data='3')]] + context.bot.send_message(chat_id=update.effective_chat.id, text=update.message.text,reply_markup=InlineKeyboardMarkup(keyboard)) + + +dispatcher.add_handler( CommandHandler('test', test)) + +def echo(update,context): + logger = logging.getLogger() +# logger.info("echo") + if update.effective_chat.id in workflows: +# text= "Current State is: %s" % workflows[update.effective_chat.id].current_state +# context.bot.send_message(chat_id=update.effective_chat.id, text=text) + workflows[update.effective_chat.id].message_handler(update,context) + +def command(update,context): + if update.effective_chat.id in workflows: + workflows[update.effective_chat.id].command_handler(update,context) + + +def button(update, context): + if update.effective_chat.id in workflows: + workflows[update.effective_chat.id].button_handler(update,context) + + #query = update.callback_query + #query.edit_message_text(text="Selected option: {}".format(que#ry.data)) + + +dispatcher.add_handler(CallbackQueryHandler(button)) + + +echo_handler = MessageHandler(Filters.text & (~Filters.command), echo) +dispatcher.add_handler(echo_handler) + +command_handler = MessageHandler(Filters.command, command) +dispatcher.add_handler(command_handler) + + +print("Added Echo") + +updater.start_polling() +#app.run() \ No newline at end of file diff --git a/bot/__init__.py b/bot/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/bot/states.py b/bot/states.py new file mode 100644 index 0000000..6aebd37 --- /dev/null +++ b/bot/states.py @@ -0,0 +1,113 @@ +from statemachine import StateMachine, State +from telegram import InlineKeyboardButton,InlineKeyboardMarkup + +import logging +logger=logging.getLogger() + +class TelegramStateMachine(StateMachine): + def __init__(self,chat_id=None, context=None*args,**kwargs): + self.chat_id = chat_id + self.user_id = user_id + self.context=context + + super().__init__(*args,**kwargs) + + def send(self,text:str): + self.context.bot.send_message(chat_id=self.chat_id, text=text) + + def send_confirm(self,text:str): + keyboard = [[InlineKeyboardButton("OK", callback_data='ok'), + InlineKeyboardButton("Repeat", callback_data='retry')], + [ InlineKeyboardButton("Cancel", callback_data='cancel')] ] + #, + # InlineKeyboardButton("Cancel", callback_data='3')] + #keyboard = [[InlineKeyboardButton("OK", callback_data='1'), + #]] + + self.context.bot.send_message(chat_id=self.chat_id, + text=text, + reply_markup=InlineKeyboardMarkup(keyboard)) + + + +class CreatePostWorkflow(TelegramStateMachine): + init =State('init', initial=True) + + wait = State('wait',value=0) + confirm =State('confirm') + finished = State('finished') + + initialize = init.to(wait) + entered = wait.to(confirm) + next=confirm.to(wait) + retry=confirm.to(wait) + + steps={ + 0:'title', + 1:'text' + } + + finish =confirm.to(finished) + cancel = finished.from_(wait,confirm) + @property + def value(self): + return self.p[self.steps[self.step]] + + def __init__(self,chat_id=None, context=None,*args, **kwargs): + super().__init__(chat_id, context, *args, **kwargs) + self.p=dict() + self.step=0 + self.initialize() + + + def confirmed(self): + if self.step >= len(self.steps)-1: + self.finish() + else: + self.next() + + def message_handler(self,update,context): + if self.current_state==self.wait: + self.p[self.steps[self.step]]=update.message.text + self.send(str(self.p)) + self.entered() + elif self.current_state==self.confirm: + if update.message.text=="ok": + self.confirmed() + else: + self.retry() + #file = bot.getFile(update.message.photo[-1].file_id + + def button_handler(self, update, context): + query = update.callback_query + if self.current_state ==self.confirm: + if query.data=='ok': + self.confirmed() + elif query.data=='cancel': + self.cancel() + else: + self.retry() + query.edit_message_text(text="Selected option: {}".format(query.data)) + + def command_handler(self,update,context): + logger.info("Processing Command: %s" % update.message.text) + + def on_next(self): + self.step+=1 + + def on_cancel(self): + self.p={} + self.step=0 + self.send("Canceled") + + def on_finish(self): + self.step=0 + self.send("Eingabe fertig:%s" % str(self.p)) + + def on_enter_confirm(self): + self.send_confirm("Bitte die Eingabe von %s bestaetigen" % self.value) + + def on_enter_wait(self): + self.send("Bitte folgendes das Attribut %s eingeben " % self.steps[self.step]) + + diff --git a/bot1/__init__.py b/bot1/__init__.py new file mode 100644 index 0000000..0519ecb --- /dev/null +++ b/bot1/__init__.py @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/bot1/chats.py b/bot1/chats.py new file mode 100644 index 0000000..641f593 --- /dev/null +++ b/bot1/chats.py @@ -0,0 +1,10 @@ +class Chat(): + def __init__(id): + self.id=id + + +class ChatManager(): + def __init__(): + self.chats=dict() + + \ No newline at end of file diff --git a/bot1/states.py b/bot1/states.py new file mode 100644 index 0000000..090240c --- /dev/null +++ b/bot1/states.py @@ -0,0 +1,128 @@ +from statemachine import StateMachine, State +from pytgbot.api_types.sendable.reply_markup import InlineKeyboardButton,InlineKeyboardMarkup + +import logging +logger=logging.getLogger() + +class TelegramStateMachine(StateMachine): + def __init__(self,chat_id=None, bot=None,*args,**kwargs): + self.chat_id = chat_id + self.user_id = user_id +# self.context=context + self.bot = bot + super().__init__(*args,**kwargs) + + def send(self,text:str): + self.bot.send_message(chat_id=self.chat_id, text=text) + + def send_confirm(self, text:str): + keyboard = [[InlineKeyboardButton("OK", callback_data='ok'), + InlineKeyboardButton("Repeat", callback_data='retry')], + [ InlineKeyboardButton("Cancel", callback_data='cancel')] ] + #, + # InlineKeyboardButton("Cancel", callback_data='3')] + #keyboard = [[InlineKeyboardButton("OK", callback_data='1'), + #]] + + self.bot.send_message(chat_id=self.chat_id, + text=text, + reply_markup=InlineKeyboardMarkup(keyboard)) + + + +class CreatePostWorkflow(TelegramStateMachine): + init =State('init', initial=True) + + wait = State('wait',value=0) + confirm =State('confirm') + finished = State('finished') + + initialize = init.to(wait) + entered = wait.to(confirm) + next=confirm.to(wait) + retry=confirm.to(wait) + + steps={ + 0:'title', + 1:'text' + } + + finish =confirm.to(finished) + cancel = finished.from_(wait,confirm) + @property + def value(self): + return self.p[self.steps[self.step]] + + def __init__(self,chat_id=None, context=None,*args, **kwargs): + super().__init__(chat_id, context, *args, **kwargs) + self.p=dict() + self.step=0 + self.initialize() + + + def confirmed(self): + if self.step >= len(self.steps)-1: + self.finish() + else: + self.next() + + # processing messages + def process_message(self, text, is_callback=False): + if self.current_state==self.wait: + self.p[self.steps[self.step]]=text + self.send(str(self .p)) + self.entered() + elif self.current_state==self.confirm: + if text=="ok": + self.confirmed() + elif query.data=='cancel': + self.cancel() + else: + self.retry() + + def button_handler(self, update, context): + query = update.callback_query + if self.current_state ==self.confirm: + if query.data=='ok': + self.confirmed() + elif query.data=='cancel': + self.cancel() + else: + self.retry() + query.edit_message_text(text="Selected option: {}".format(query.data)) + + def command_handler(self,update,context): + logger.info("Processing Command: %s" % update.message.text) + + def message_handler(self,update,context): + if self.current_state==self.wait: + self.p[self.steps[self.step]]=update.message.text + self.send(str(self.p)) + self.entered() + elif self.current_state==self.confirm: + if update.message.text=="ok": + self.confirmed() + else: + self.retry() + #file = bot.getFile(update.message.photo[-1].file_id + + + def on_next(self): + self.step+=1 + + def on_cancel(self): + self.p={} + self.step=0 + self.send("Canceled") + + def on_finish(self): + self.step=0 + self.send("Eingabe fertig:%s" % str(self.p)) + + def on_enter_confirm(self): + self.send_confirm("Bitte die Eingabe von %s bestaetigen" % self.value) + + def on_enter_wait(self): + self.send("Bitte folgendes das Attribut %s eingeben " % self.steps[self.step]) + + diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 0000000..ff8cf9d --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,13 @@ +version: '3' +services: + solr: + image: solr:8 + ports: + - "8980:8983" + volumes: + - data:/var/solr + command: + - solr-precreate + - gettingstarted +volumes: + data: diff --git a/fet2020api/__init__.py b/fet2020api/__init__.py new file mode 100644 index 0000000..bd9dac9 --- /dev/null +++ b/fet2020api/__init__.py @@ -0,0 +1,38 @@ +import requests +from .djangoapi import django_crud_api +class fet2020postapi(django_crud_api): + def __init__(self,endpoint="http://localhost:8106/api/posts/"): + super().__init__(endpoint=endpoint) + + def read_post(self, slug=None,legacy_id=None): + return self.find_one({'slug':slug,'legacy_id':legacy_id}) + + def update_or_write_by_legacy_id(self,d): + if not 'legacy_id' in d: + raise AttributeError('legacy_id muss angegeben werden') + p=self.read_post(legacy_id=d['legacy_id']) + if p is None: + p=self.create(d) + else: + p=self.update(p['slug'], d) + return p + def push(self,d): + return self.update_or_write_by_legacy_id(d) + +class fet2020memberapi(django_crud_api): + def __init__(self, endpoint= "http://localhost:8103/api/members/"): + super().__init__(endpoint=endpoint) + + def read_post(self, slug=None,legacy_id=None): + return self.find_one({'nickname':slug,'legacy_id':legacy_id}) + + def update_or_write_by_legacy_id(self,d): + if not 'legacy_id' in d: + raise AttributeError('legacy_id muss angegeben werden') + p=self.read_post(legacy_id=d['legacy_id']) + if p is None: + p=self.create(d) + else: + p=self.update(p['slug'], d) + return p + \ No newline at end of file diff --git a/fet2020api/djangoapi.py b/fet2020api/djangoapi.py new file mode 100644 index 0000000..5ecfad8 --- /dev/null +++ b/fet2020api/djangoapi.py @@ -0,0 +1,76 @@ +import requests +from urllib.parse import urljoin +import json +class django_crud_api(): + def __init__(self,**kwargs): + self.endpoint=kwargs.get('endpoint') + + def find(self, filter): + try: + r = requests.request('GET', self.endpoint, params={'format':'json',**filter}) + r.raise_for_status() + r=r.json() + except requests.exceptions.RequestException as e: + print(e) + return None + return r + def find_one(self,filter): + r=self.find(filter) + if r is None: + return None + if len(r)>1: + raise LookupError("Mehr als ein Objekt von der API zurückgegeben") + if len(r)==0: + return None + return r[0] + + def get(self,pk): + try: + r = requests.request('GET', urljoin(self.endpoint,pk), params={'format':'json'}) + r=r.json() + except requests.exceptions.RequestException as e: + print(e) + return None + return r + + def update(self,pk,d): + try: + files=d.pop("files",None) + headers = None #{'Content-type': 'multipart/form-data'} + print("Updated %s " % pk) + r = requests.request('PUT', urljoin(self.endpoint,pk)+"/", headers=headers,data=d,files=files) + r.raise_for_status() + except requests.exceptions.RequestException as e: + print(e) + if r: + print(r.text) + print(d.keys()) + print("Tryed to reach %s with PUT Action" % urljoin(self.endpoint,pk)) + return None + + + if r.status_code==200: + r=r.json() + + return r + + def create(self, d): + try: + files=d.pop("files",None) + headers = None #{'Content-type': 'application/json'} + print("Create %s" % d["slug"]) + # print("Create with data %s" % str(d)) + r = requests.post(self.endpoint,headers=headers,data=d,files=files) + r.raise_for_status() + except requests.exceptions.RequestException as e: + print(e) + if r and r.status_code==400: + print(r.text) + print("Tryed to reach %s with POST Action" % self.endpoint) + + + return None + if r.status_code==200: + return r.json() + print(r) + return r diff --git a/solr.py b/solr.py new file mode 100644 index 0000000..56ac80a --- /dev/null +++ b/solr.py @@ -0,0 +1,14 @@ +from fet2020api import fet2020postapi +import pysolr +import python-environ + +solr=pysolr.Solr('http://localhost:8980/solr/gettingstarted', always_commit=True) + + +# reindex posts from alpha + +TARGET= "https://alpha.2020.fet.at" + + + +solr.add() diff --git a/spacytest.py b/spacytest.py new file mode 100644 index 0000000..3bf5e5f --- /dev/null +++ b/spacytest.py @@ -0,0 +1,20 @@ +import spacy + + +q= "Hast du beispiele für Mathe1?" + +nlp=spacy.load('de_core_news_md') +d=nlp(q) + + +print(d.text) + +print([t for t in d]) + +print([t.tag_ for t in d]) + +print([t.lemma_ for t in d]) + +print([spacy.explain(t.tag_) for t in d]) + + diff --git a/test.py b/test.py new file mode 100644 index 0000000..8fc3773 --- /dev/null +++ b/test.py @@ -0,0 +1,74 @@ +import logging + +from telegram.ext import CommandHandler, CallbackQueryHandler +from telegram.ext import Updater +from telegram import InlineKeyboardButton,InlineKeyboardMarkup + +from telegram.ext import MessageHandler, Filters + +updater = Updater(token='317750953:AAFzRryrTGUhnaaHgXfvVUkvk5WKgyTQ7CU', use_context=True) +dispatcher = updater.dispatcher +logger = logging.getLogger() +logger.setLevel(logging.INFO) + +workflows = {} + + +def start(update, context): + logger.info("start") + keyboard = [[InlineKeyboardButton("Option 1", callback_data='1'), + InlineKeyboardButton("Option 2", callback_data='2')], + [InlineKeyboardButton("Option 3", callback_data='3')]] + + reply_markup = InlineKeyboardMarkup(keyboard) + update.message.reply_text('Please choose:', reply_markup=reply_markup) + + + #context.bot.send_message(chat_id=update.effective_chat.id, text="I'm a bot, please talk to me!") + +start_handler = CommandHandler('start', start) +dispatcher.add_handler(start_handler) +print("StartCommand") + +def echo(update, context): + logger.info("echo") + context.bot.send_message(chat_id=update.effective_chat.id, text=update.message.text) + +echo_handler = MessageHandler(Filters.text & (~Filters.command), echo) +dispatcher.add_handler(echo_handler) +print("Added Echo") + +def caps(update, context): + text_caps = ' '.join(context.args).upper() + context.bot.send_message(chat_id=update.effective_chat.id, text=text_caps) + +caps_handler = CommandHandler('caps', caps) +dispatcher.add_handler(caps_handler) + +from telegram import InlineQueryResultArticle, InputTextMessageContent +def inline_caps(update, context): + query = update.inline_query.query + if not query: + return + results = list() + results.append( + InlineQueryResultArticle( + id=query.upper(), + title='Caps', + input_message_content=InputTextMessageContent(query.upper()) + ) + ) + context.bot.answer_inline_query(update.inline_query.id, results) + +from telegram.ext import InlineQueryHandler +inline_caps_handler = InlineQueryHandler(inline_caps) +dispatcher.add_handler(inline_caps_handler) + + +def button(update, context): + query = update.callback_query + query.edit_message_text(text="Selected option: {}".format(query.data)) +updater.dispatcher.add_handler(CallbackQueryHandler(button)) + + +updater.start_polling() \ No newline at end of file diff --git a/test2.py b/test2.py new file mode 100644 index 0000000..8b1ff48 --- /dev/null +++ b/test2.py @@ -0,0 +1,99 @@ + +from flask import Flask +from flask import request +from teleflask import Teleflask +from teleflask.messages import TextMessage +from key import API_KEY +import logging +import yaml +logging.basicConfig(level=logging.INFO) +URL_HOSTNAME='bot.2020.fet.at' +import requests +from bot1.states import CreatePostWorkflow +from pytgbot.api_types.sendable.reply_markup import InlineKeyboardButton,InlineKeyboardMarkup + +app=Flask(__name__) +chat_id='108021014' +bot = Teleflask(API_KEY) +bot.init_app(app) + + + +@app.route('/') +def home(): + return "Home" + +@app.route('/send/') +def send(text=None): + + bot.bot.send_message(chat_id, text) + return "Text: %s
%s" % (text,request.headers) + + +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 + + +@bot.command("start") +def start(update, text): + m=update.message.to_array() + fn=m["from"]["first_name"] + return bot.bot.send_message(m["chat"]["id"],"Hello "+fn, parse_mode='html',reply_to_message_id=None) + +def send_confirm( chat_id, text:str): + keyboard = [[InlineKeyboardButton("OK", callback_data='ok'), + InlineKeyboardButton("Repeat", callback_data='retry')], + [ InlineKeyboardButton("Cancel", callback_data='cancel')] ] + + bot.bot.send_message(chat_id=chat_id, + text=text, + reply_markup=InlineKeyboardMarkup(keyboard)) + + +@bot.command("confirm") +def confirm(update,text): + send_confirm(update.message.chat.id, "Please Confirm") + +@bot.on_update +def bot_update(update): + + from pytgbot.api_types.receivable.updates import Update + assert isinstance(update, Update) + + print(yaml.dump(update.to_array())) + + message=update.message + if message and message.entities and update.message.entities[0].type=="bot_command": + return bot.bot.send_msg(text="Hello World",chat_id=message.chat.id,reply_to_message_id=update.message.message_id) + + if message and message.photo: + ff=max(update.message.photo, key=lambda x: x.file_size) + fff = bot.bot.get_file(ff.file_id) + + download_file(fff.get_download_url(API_KEY)) + + return TextMessage("I download it!: %s" % str(fff.get_download_url(API_KEY))) + + if update.callback_query: + bot.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 not update.message: + return + return TextMessage("Message: %s" % str(update.message)) + + +app.run(host="0.0.0.0",port="5000",debug=True)