-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
04cacf8
commit f6f9e7f
Showing
14 changed files
with
633 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,2 +1,11 @@ | ||
# f11nbot | ||
a telegram bot for supporting offline conversations | ||
|
||
## run migrations | ||
|
||
`python manage.py migrate` | ||
|
||
## run commands for creating games and promos | ||
|
||
`python manage.py generate_games` | ||
`python manage.py generate_promo` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
# coding=utf-8 | ||
""" | ||
Строковые константы для кнопок | ||
""" | ||
|
||
EXIT_CMD = u"Выход" | ||
GAME_OVER_MSG = u"Игра окончена" | ||
|
||
ASK_FOR_PROMO_MSG = u"Чтобы продолжить, введите сюда промокод, который выдал вам таймпад при покупке билета" | ||
NEXT_QUESTION_CMD = u"Следующий вопрос" | ||
BACK_CMD = u"Назад" | ||
START_MSG = u"Приветствую! Это бот Факторизация отношений" | ||
PARTNER_MSG = u"Ваш партнер уже тут, и вы в игре" | ||
SEND_PROMO_MSG = u"Это игра на двоих! Перешлите промокод своему партнеру. Когда он/она присоединится, начнется игра" | ||
NO_SUCH_GAME_MSG = u"Такой игры нет!" | ||
HELP_MSG = START_MSG # TODO make help | ||
WAIT_FOR_PARTNER_MSG = u'Чтобы двинуться дальше, ваш партнер должен тоже нажать "Следующий вопрос"' | ||
FINISH_FACT_CMD = u'Закончить факторизацию' | ||
START_CMD = u'Начать' | ||
NO_MORE_QUESTIONS_MSG = u'Вопросов в этой категории больше нет' | ||
SELECT_CATEGORY_MSG = u"Для начала выберите фактор, который хотели бы обсудить подробнее. Внимание! Игра не начнется пока оба партнера не выберут один и тот же фактор" |
Empty file.
Empty file.
Empty file.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,54 @@ | ||
# -*- coding: utf-8 -*- | ||
import os | ||
import csv | ||
from django.core.management.base import BaseCommand, CommandError | ||
from data.models import Game, Discussion, QuestionCategory, Question | ||
|
||
from collections import OrderedDict | ||
|
||
|
||
class Command(BaseCommand): | ||
help = 'Creates StVal Discussion + Promos' | ||
|
||
@staticmethod | ||
def read_questions(path): | ||
with open(path, 'r') as f: | ||
reader = csv.reader(f) | ||
return {int(l[0]): [l[1], int(l[2])] for l in reader} | ||
|
||
@staticmethod | ||
def read_categories(path): | ||
with open(path, 'r') as f: | ||
reader = csv.reader(f) | ||
return OrderedDict([(int(l[0]), l[1]) for l in reader]) | ||
|
||
def handle(self, *args, **options): | ||
discussion, created = Discussion.objects.get_or_create( | ||
name="StVal", | ||
user_limit=2 | ||
) | ||
|
||
fact_game, fact_created = Game.objects.get_or_create( | ||
name=u'Факторизация', | ||
choose_command=u"факторизация", | ||
discussion=discussion, | ||
description=u"В этой игре бот предложит рассмотреть ваши отношения как набор различных факторов и задаст вопросы про каждый из них по отдельности" | ||
) | ||
fact_game.save() | ||
|
||
root_dir = os.path.dirname(os.path.join(os.path.dirname(__file__), '..', '..', '..', '..')) | ||
categories = self.read_categories(os.path.join(root_dir, 'storage/fact_categories.csv')) | ||
questions = self.read_questions(os.path.join(root_dir, 'storage/fact_questions.csv')) | ||
for category_id, name in categories.items(): | ||
category, cat_created = QuestionCategory.objects.get_or_create( | ||
name=name, | ||
game=fact_game | ||
) | ||
for question, question_data in questions.items(): | ||
if question_data[1] == category.id: | ||
question, question_created = Question.objects.get_or_create( | ||
text=question_data[0] | ||
) | ||
category.questions.add(question) | ||
|
||
self.stdout.write(self.style.SUCCESS(u'Successfully created game "%s"' % fact_game)) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
from django.core.management.base import BaseCommand, CommandError | ||
from data.models import PromoCode, Discussion | ||
|
||
import csv | ||
|
||
class Command(BaseCommand): | ||
help = 'Creates StVal Discussion + Promos' | ||
|
||
def handle(self, *args, **options): | ||
stValDiscussion, disc_created = Discussion.objects.get_or_create( | ||
name="StVal", | ||
user_limit=2 | ||
) | ||
with open('storage/promo_codes.csv', 'r') as f: | ||
reader = csv.reader(f) | ||
|
||
for promo_code in reader: | ||
promo, created = PromoCode.objects.get_or_create( | ||
discussion=stValDiscussion, | ||
code=promo_code[1] | ||
) | ||
self.stdout.write(self.style.SUCCESS('Successfully created promo_code "%s"' % promo_code[1])) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,120 @@ | ||
# -*- coding: utf-8 -*- | ||
from telegram import InlineKeyboardButton, InlineKeyboardMarkup | ||
from telegram import ReplyKeyboardMarkup, KeyboardButton | ||
from django.db import models | ||
from django.contrib.postgres.fields import JSONField | ||
|
||
from const import * | ||
|
||
|
||
class User(models.Model): | ||
telegram_id = models.IntegerField() | ||
first_name = models.CharField(max_length=255) | ||
last_name = models.CharField(max_length=255) | ||
username = models.CharField(max_length=255) | ||
|
||
|
||
class Discussion(models.Model): | ||
name = models.CharField(max_length=255) | ||
user_limit = models.IntegerField() | ||
members = models.ManyToManyField(User, through='DiscussionMembership') | ||
|
||
|
||
class PromoCode(models.Model): | ||
code = models.CharField(max_length=255) | ||
discussion = models.ForeignKey(Discussion, on_delete=models.CASCADE) | ||
|
||
|
||
BANNED_FACTORS_LEN = 4 | ||
CHOSEN_FACTORS_LEN = 4 | ||
|
||
START_USER_STATE = { | ||
'category': 0, | ||
'question': 0 | ||
} | ||
|
||
|
||
class Game(models.Model): | ||
name = models.CharField(max_length=255) | ||
choose_command = models.CharField(max_length=255) | ||
discussion = models.ForeignKey(Discussion, on_delete=models.CASCADE) | ||
description = models.TextField(blank=True) | ||
|
||
def process_state(self, state, msg_text): | ||
fact_name = u'Факторизация' | ||
if self.name == fact_name: | ||
return self.process_fact_state(state, msg_text) | ||
else: | ||
send_text = GAME_OVER_MSG | ||
keyboard = [[InlineKeyboardButton(NEXT_QUESTION_CMD)]] | ||
reply_markup = ReplyKeyboardMarkup(keyboard, one_time_keyboard=True) | ||
return state, send_text, reply_markup | ||
|
||
def process_fact_state(self, state, msg_text): | ||
msg_text = msg_text.replace('/', '') | ||
# TODO reorder game cats | ||
game_categories = self.questioncategory_set.all() | ||
|
||
if state.get('category'): | ||
matched_categories = game_categories.filter(id=state.get('category')) | ||
else: | ||
matched_categories = game_categories.filter(name__contains=msg_text) | ||
|
||
if state.get('category') or matched_categories: | ||
|
||
matched_category = matched_categories[0] | ||
state['category'] = matched_category.id | ||
|
||
cat_questions = list(matched_category.questions.all()) | ||
|
||
if state.get('question') >= len(cat_questions): | ||
send_text = NO_MORE_QUESTIONS_MSG | ||
state = START_USER_STATE.copy() | ||
|
||
keyboard = [[InlineKeyboardButton(BACK_CMD)]] | ||
else: | ||
current_question = cat_questions[state.get('question')] | ||
send_text = current_question.text | ||
|
||
state['question'] += 1 | ||
|
||
keyboard = [[InlineKeyboardButton(NEXT_QUESTION_CMD)], | ||
[InlineKeyboardButton(BACK_CMD)]] | ||
reply_markup = ReplyKeyboardMarkup(keyboard, one_time_keyboard=True) | ||
else: | ||
send_text = SELECT_CATEGORY_MSG | ||
|
||
fact_cats = [ | ||
[KeyboardButton("{}".format(cat.name))] for cat in reversed(game_categories) | ||
] | ||
fact_cats.append([KeyboardButton(FINISH_FACT_CMD)]) | ||
reply_markup = ReplyKeyboardMarkup(fact_cats, one_time_keyboard=True) | ||
state['category'] = 0 | ||
|
||
return state, send_text, reply_markup | ||
|
||
def __unicode__(self): | ||
return self.name | ||
|
||
|
||
class Question(models.Model): | ||
text = models.TextField(blank=True) | ||
|
||
class Meta: | ||
ordering = ['id'] | ||
|
||
|
||
class QuestionCategory(models.Model): | ||
game = models.ForeignKey(Game, on_delete=models.CASCADE) | ||
name = models.CharField(max_length=255) | ||
questions = models.ManyToManyField(Question) | ||
|
||
|
||
class DiscussionMembership(models.Model): | ||
user = models.ForeignKey(User, on_delete=models.CASCADE) | ||
discussion = models.ForeignKey(Discussion, on_delete=models.CASCADE) | ||
state = JSONField(null=True) | ||
promo_code = models.CharField(max_length=255) | ||
active_game = models.ForeignKey(Game, null=True, on_delete=models.SET_NULL) | ||
ready = models.BooleanField(default=False) | ||
category = models.CharField(max_length=255,null=True) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
""" | ||
WSGI config for test_projecrt project. | ||
It exposes the WSGI callable as a module-level variable named ``application``. | ||
For more information on this file, see | ||
https://docs.djangoproject.com/en/1.10/howto/deployment/wsgi/ | ||
""" | ||
|
||
import os | ||
|
||
from django.core.wsgi import get_wsgi_application | ||
|
||
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "test_projecrt.settings") | ||
|
||
application = get_wsgi_application() |
Oops, something went wrong.