├── runtime.txt
├── templates
├── profile.css
├── result.html
├── __init__.py
├── attachment.py
├── quick_replies.py
├── text.py
├── button.py
├── generic.py
├── profile.html
└── receipt.py
├── static
├── endchat.jpg
├── endchat1.jpg
├── gifs
│ ├── giphy.gif
│ ├── giphy-downsized.gif
│ ├── giphy-downsized (1).gif
│ └── giphy-downsized (2).gif
└── startchat.jpg
├── DB_Wrappers
├── __init__.py
├── WaitingList.py
├── ActiveChats.py
└── Users.py
├── Procfile
├── manage.py
├── modules
├── __init__.py
├── image.py
├── gifs.py
├── interrupts.py
├── quick_replies.py
├── postback.py
├── campaign.py
├── critical_operations.py
├── setup.py
├── debug.py
├── gamification.py
├── subscription.py
├── alias.py
├── startChat.py
├── utilities.py
└── endChat.py
├── requirements.txt
├── config.py
├── analytics.py
├── .gitignore
├── LICENSE
├── models.py
├── README.md
└── app.py
/runtime.txt:
--------------------------------------------------------------------------------
1 | python-2.7.14
2 |
--------------------------------------------------------------------------------
/templates/profile.css:
--------------------------------------------------------------------------------
1 | .container-fluid{
2 | background: #f5d9d5;
3 | }
--------------------------------------------------------------------------------
/static/endchat.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mayukh18/BlindChat/HEAD/static/endchat.jpg
--------------------------------------------------------------------------------
/static/endchat1.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mayukh18/BlindChat/HEAD/static/endchat1.jpg
--------------------------------------------------------------------------------
/static/gifs/giphy.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mayukh18/BlindChat/HEAD/static/gifs/giphy.gif
--------------------------------------------------------------------------------
/static/startchat.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mayukh18/BlindChat/HEAD/static/startchat.jpg
--------------------------------------------------------------------------------
/static/gifs/giphy-downsized.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mayukh18/BlindChat/HEAD/static/gifs/giphy-downsized.gif
--------------------------------------------------------------------------------
/static/gifs/giphy-downsized (1).gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mayukh18/BlindChat/HEAD/static/gifs/giphy-downsized (1).gif
--------------------------------------------------------------------------------
/static/gifs/giphy-downsized (2).gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mayukh18/BlindChat/HEAD/static/gifs/giphy-downsized (2).gif
--------------------------------------------------------------------------------
/DB_Wrappers/__init__.py:
--------------------------------------------------------------------------------
1 | from Users import UsersDB
2 | from ActiveChats import ActiveChatsDB
3 | from WaitingList import WaitingListDB
--------------------------------------------------------------------------------
/Procfile:
--------------------------------------------------------------------------------
1 | web: python manage.py runserver --host 0.0.0.0 --port ${PORT}
2 | init: python manage.py db init
3 | migrate: python manage.py db migrate
4 | upgrade: python manage.py db upgrade
5 |
--------------------------------------------------------------------------------
/templates/result.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Title
6 |
7 |
8 |
9 | INTERESTS AND BIO SAVED
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/manage.py:
--------------------------------------------------------------------------------
1 | from flask_script import Manager
2 | from flask_migrate import Migrate, MigrateCommand
3 |
4 | from app import app, db, setup_all
5 |
6 | migrate = Migrate(app, db)
7 |
8 | manager = Manager(app)
9 | manager.add_command('db', MigrateCommand)
10 |
11 |
12 | if __name__ == '__main__':
13 | setup_all()
14 | manager.run()
--------------------------------------------------------------------------------
/modules/__init__.py:
--------------------------------------------------------------------------------
1 | from postback import handle_postback
2 | from utilities import send_message, send_help, isGreeting, handle_greetings
3 | from interrupts import Interrupts
4 | from quick_replies import handle_quick_reply
5 | from image import handle_image
6 | from setup import setup_all
7 | from debug import handle_debug
8 | from gamification import Game
--------------------------------------------------------------------------------
/requirements.txt:
--------------------------------------------------------------------------------
1 | alembic==0.9.2
2 | Flask==0.10.1
3 | Flask-Migrate==2.0.4
4 | Flask-Script==2.0.5
5 | Flask-SQLAlchemy==2.2
6 | gunicorn==19.6.0
7 | html5lib==1.0b8
8 | Jinja2==2.8
9 | jsonschema==2.5.1
10 | requests==2.17.3
11 | requests-cache==0.4.13
12 | simplejson==3.10.0
13 | six==1.10.0
14 | SQLAlchemy==1.1.10
15 | sqlalchemy-migrate==0.11.0
16 | psycopg2==2.7.1
--------------------------------------------------------------------------------
/templates/__init__.py:
--------------------------------------------------------------------------------
1 | from text import TextTemplate
2 | from generic import GenericTemplate
3 | from button import ButtonTemplate
4 | from quick_replies import add_quick_reply
5 | from attachment import AttachmentTemplate
6 |
7 | __all__ = [
8 | 'TextTemplate',
9 | 'GenericTemplate',
10 | 'ButtonTemplate',
11 | 'add_quick_reply',
12 | 'AttachmentTemplate'
13 | ]
--------------------------------------------------------------------------------
/config.py:
--------------------------------------------------------------------------------
1 | import os
2 | basedir = os.path.abspath(os.path.dirname(__file__))
3 |
4 | # Database setup
5 | SQLALCHEMY_DATABASE_URI = 'YOUR_DATABASE_URI'
6 | SQLALCHEMY_MIGRATE_REPO = os.path.join(basedir, 'db_repository')
7 | SQLALCHEMY_TRACK_MODIFICATIONS = False
8 |
9 | # Facebook
10 | ACCESS_TOKEN = 'YOUR_FACEBOOK_APP_ACCESS_TOKEN'
11 | VERIFY_TOKEN = 'FACEBOOK_APP_VERIFY_TOKEN'
12 |
13 | # App url
14 | APP_URL = 'APP_URL'
15 |
16 | # For analytics purposes
17 | CHATMETRICS_TOKEN = 'CHATMETRICS_TOKEN'
18 |
19 | # For debugging
20 | PAGE_ID = 'FACEBOOK_PAGE_PSID'
21 | ADMIN_ID = "ADMIN_PSID"
22 |
23 |
--------------------------------------------------------------------------------
/analytics.py:
--------------------------------------------------------------------------------
1 | import os
2 | import json
3 | import config
4 | import requests
5 |
6 | class Analytics:
7 | def __init__(self):
8 | self.token = os.environ.get('CHATMETRICS_TOKEN', config.CHATMETRICS_TOKEN)
9 |
10 | def record(self, entry):
11 | try:
12 | data = {"object":"page"}
13 | data["entry"] = entry
14 | r = requests.post(url="https://api.chatbottle.co/v2/updates/messenger/"+self.token+"/", data=json.dumps(data))
15 | print("analytics result", r.json(), data)
16 | except Exception, e:
17 | print("ANALYTICS ERROR", str(e))
18 |
19 |
20 |
--------------------------------------------------------------------------------
/modules/image.py:
--------------------------------------------------------------------------------
1 | from templates import AttachmentTemplate, TextTemplate
2 | from app import activechatsdb
3 | from utilities import send_message
4 |
5 | def handle_image(sender, url):
6 | try:
7 | partner = activechatsdb.get_partner(sender)
8 | alias = activechatsdb.get_alias(sender)
9 | message = TextTemplate(text=alias+" has sent you an image.")
10 | send_message(message.get_message(), id=partner)
11 | message = AttachmentTemplate(url=url, type='image')
12 | send_message(message.get_message(), id=partner)
13 | #dummy1
14 | except Exception, e:
15 | print("IMAGE ERROR", str(e))
--------------------------------------------------------------------------------
/modules/gifs.py:
--------------------------------------------------------------------------------
1 | _male_start_hi = ['https://media.giphy.com/media/dzaUX7CAG0Ihi/giphy-downsized.gif',
2 | 'https://media.giphy.com/media/oJiCqvIqPZE3u/giphy.gif']
3 |
4 | _female_start_hi = ['https://media.giphy.com/media/a1QLZUUtCcgyA/giphy-downsized.gif',
5 | 'https://media.giphy.com/media/EPJZhOrStSpz2/giphy-downsized.gif']
6 |
7 | import random
8 | def get_start_hi(gender):
9 | if gender == "male":
10 | #return random.choice(_male_start_hi)
11 | return _male_start_hi[1]
12 | elif gender == "female":
13 | #return random.choice(_female_start_hi)
14 | return _female_start_hi[1]
15 | else:
16 | return random.choice(_male_start_hi)
--------------------------------------------------------------------------------
/templates/attachment.py:
--------------------------------------------------------------------------------
1 | template = {
2 | 'template_type': 'attachment',
3 | 'value': {
4 | 'attachment': {
5 | 'type': 'file',
6 | 'payload': {
7 | 'url': ''
8 | }
9 | }
10 | }
11 | }
12 |
13 | class AttachmentTemplate:
14 | def __init__(self, url='', type='file'):
15 | self.template = template['value']
16 | self.url = url
17 | self.type = type
18 | def set_url(self, url=''):
19 | self.url = url
20 | def set_type(self, type=''):
21 | # image / audio / video / file
22 | self.type = type
23 | def get_message(self):
24 | self.template['attachment']['payload']['url'] = self.url
25 | self.template['attachment']['type'] = self.type
26 | return self.template
27 |
--------------------------------------------------------------------------------
/templates/quick_replies.py:
--------------------------------------------------------------------------------
1 | from copy import deepcopy as copy
2 |
3 | QUICK_REPLIES_LIMIT = 11
4 | TITLE_CHARACTER_LIMIT = 20
5 | PAYLOAD_CHARACTER_LIMIT = 1000
6 |
7 | def add_quick_reply(message, title='', payload=''):
8 | message_with_quick_reply = copy(message)
9 | if 'quick_replies' not in message_with_quick_reply:
10 | message_with_quick_reply['quick_replies'] = []
11 | if len(message_with_quick_reply['quick_replies']) < QUICK_REPLIES_LIMIT:
12 | quick_reply = {}
13 | # TODO: location + image_url
14 | quick_reply['content_type'] = 'text'
15 | quick_reply['title'] = title[:TITLE_CHARACTER_LIMIT]
16 | quick_reply['payload'] = payload[:PAYLOAD_CHARACTER_LIMIT]
17 | message_with_quick_reply['quick_replies'].append(quick_reply)
18 | return message_with_quick_reply
19 |
--------------------------------------------------------------------------------
/templates/text.py:
--------------------------------------------------------------------------------
1 | TEXT_CHARACTER_LIMIT = 640
2 |
3 | template = {
4 | 'template_type': 'text',
5 | 'value': {
6 | 'text': ''
7 | }
8 | }
9 |
10 | class TextTemplate:
11 | def __init__(self, text='', post_text='', limit=TEXT_CHARACTER_LIMIT):
12 | self.template = template['value']
13 | self.text = text
14 | self.post_text = post_text
15 | self.limit = limit
16 | def set_text(self, text=''):
17 | self.text = text
18 | def set_post_text(self, post_text=''):
19 | self.post_text = post_text
20 | def set_limit(self, limit=TEXT_CHARACTER_LIMIT):
21 | self.limit = limit
22 | def get_message(self):
23 | n = self.limit - len(self.post_text)
24 | if n > len(self.text):
25 | self.template['text'] = self.text + self.post_text
26 | else:
27 | # append ellipsis (length = 3)
28 | self.template['text'] = self.text[:n-3].rsplit(' ', 1)[0] + '...' + self.post_text
29 | return self.template
30 |
--------------------------------------------------------------------------------
/modules/interrupts.py:
--------------------------------------------------------------------------------
1 | from utilities import send_help, send_newchat_prompt, send_profile_prompt
2 | from critical_operations import restart_bot, execute_exit
3 |
4 |
5 |
6 | class Interrupts:
7 |
8 | def __init__(self):
9 | self.commands = ["quit", "exit", "restart", "help", "start", "startchat", "profile"]
10 |
11 | def isValidCommand(self, command):
12 | text = command.lower().replace(" ", "")
13 | if text in self.commands:
14 | return True
15 | return False
16 |
17 | def handleCommand(self, command, sender):
18 | text = command.lower().replace(" ", "")
19 | print("INTERRUPT", text)
20 | if text == "help":
21 | send_help(sender)
22 | elif text == "restart":
23 | restart_bot(sender)
24 | elif text == "quit" or text == "exit":
25 | execute_exit(id = sender)
26 | elif text == "start" or text == "startchat":
27 | send_newchat_prompt(id=sender)
28 | elif text == "profile":
29 | send_profile_prompt(id=sender)
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Byte-compiled / optimized / DLL files
2 | __pycache__/
3 | *.py[cod]
4 | *$py.class
5 |
6 | .idea/
7 | migrations/
8 |
9 | # C extensions
10 | *.so
11 |
12 | # Distribution / packaging
13 | .Python
14 | env/
15 | build/
16 | develop-eggs/
17 | dist/
18 | downloads/
19 | eggs/
20 | .eggs/
21 | lib/
22 | lib64/
23 | parts/
24 | sdist/
25 | var/
26 | *.egg-info/
27 | .installed.cfg
28 | *.egg
29 |
30 | # PyInstaller
31 | # Usually these files are written by a python script from a template
32 | # before PyInstaller builds the exe, so as to inject date/other infos into it.
33 | *.manifest
34 | *.spec
35 |
36 | # Installer logs
37 | pip-log.txt
38 | pip-delete-this-directory.txt
39 |
40 | # Unit test / coverage reports
41 | htmlcov/
42 | .tox/
43 | .coverage
44 | .coverage.*
45 | .cache
46 | nosetests.xml
47 | coverage.xml
48 | *,cover
49 | .hypothesis/
50 |
51 | # Translations
52 | *.mo
53 | *.pot
54 |
55 | # Django stuff:
56 | *.log
57 |
58 | # Sphinx documentation
59 | docs/_build/
60 |
61 | # PyBuilder
62 | target/
63 |
64 | #Ipython Notebook
65 | .ipynb_checkpoints
66 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2017 Mayukh Bhattacharyya
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/modules/quick_replies.py:
--------------------------------------------------------------------------------
1 | from startChat import startChat
2 | from endChat import share_profile
3 | from subscription import handle_subscribe_payload
4 | from utilities import *
5 | from app import usersdb
6 | import json
7 |
8 | def handle_quick_reply(sender, payload):
9 | try:
10 | usersdb.setPauseStatus(id=sender, status=False)
11 | print("1")
12 | send_paused_messages(id=sender)
13 | except Exception, e:
14 | print("QUICK_REPLY_ERROR", str(e))
15 |
16 | payload = json.loads(payload)
17 | print("QUICKREPLYPAYLOAD", payload)
18 |
19 | if payload["keyword"] == "newchat":
20 | if payload["ans"] == "y":
21 | send_interest_menu(sender=sender)
22 | if payload["ans"] == "n":
23 | message = TextTemplate(text="Cool. When you come back use the menu to look for a new chat")
24 | send_message(message=message.get_message(), id = sender)
25 | if payload["ans"] == "p":
26 | send_profile_prompt(id=sender)
27 |
28 | elif payload["keyword"] == "interest":
29 | print("interest selected")
30 | startChat(sender=sender,interest=payload["interest"])
31 |
32 | elif payload["keyword"] == "profile_share":
33 | share_profile(sender, payload=payload)
34 |
35 | elif payload["keyword"] == "subscribe":
36 | handle_subscribe_payload(id=sender, payload=payload)
--------------------------------------------------------------------------------
/templates/button.py:
--------------------------------------------------------------------------------
1 | from copy import deepcopy as copy
2 |
3 | from text import TextTemplate
4 | TextTemplate.get_text = lambda self: self.get_message()['text']
5 |
6 | TEXT_CHARACTER_LIMIT = 320
7 |
8 | template = {
9 | 'template_type': 'button',
10 | 'value': {
11 | 'attachment': {
12 | 'type': 'template',
13 | 'payload': {
14 | 'template_type': 'button',
15 | 'text': '',
16 | 'buttons': []
17 | }
18 | }
19 | }
20 | }
21 |
22 | class ButtonTemplate:
23 | def __init__(self, text=''):
24 | self.template = copy(template['value'])
25 | self.text = text
26 | def add_web_url(self, title='', url=''):
27 | web_url_button = {}
28 | web_url_button['type'] = 'web_url'
29 | web_url_button['title'] = title
30 | web_url_button['url'] = url
31 | self.template['attachment']['payload']['buttons'].append(web_url_button)
32 | def add_postback(self, title='', payload=''):
33 | postback_button = {}
34 | postback_button['type'] = 'postback'
35 | postback_button['title'] = title
36 | postback_button['payload'] = payload
37 | self.template['attachment']['payload']['buttons'].append(postback_button)
38 | def set_text(self, text=''):
39 | self.text = text
40 | def get_message(self):
41 | self.template['attachment']['payload']['text'] = self.text
42 | return self.template
43 |
--------------------------------------------------------------------------------
/DB_Wrappers/WaitingList.py:
--------------------------------------------------------------------------------
1 | from models import WaitingListUser
2 |
3 | class WaitingListDB():
4 | def __init__(self, db):
5 | self.db = db
6 |
7 | def get_match(self, gender, interest):
8 | waitlist = WaitingListUser.query.all()
9 | print("WAITLIST", waitlist, gender, interest)
10 | for i in range(len(waitlist)):
11 | user = waitlist[i]
12 | print("user waiting", user.gender, user.interest)
13 | if user.interest == gender or user.interest == "random":
14 | print("IN 1")
15 | if user.gender == interest or interest == "random":
16 | print("IN 2")
17 | Id = user.id
18 | self.db.session.delete(user)
19 | self.db.session.commit()
20 | return Id
21 | print("NO MATCH FOUND")
22 | return None
23 |
24 | def enlist(self, id, gender, interest):
25 | user = WaitingListUser(id = id, gender=gender, interest=interest)
26 | self.db.session.add(user)
27 | self.db.session.commit()
28 |
29 | def isWaiting(self, id):
30 | user = WaitingListUser.query.get(id)
31 | if user is None:
32 | return False
33 | return True
34 |
35 | def delist(self, id):
36 | try:
37 | user = WaitingListUser.query.get(id)
38 | self.db.session.delete(user)
39 | self.db.session.commit()
40 | except Exception, e:
41 | print("Not in waitlist", str(e))
--------------------------------------------------------------------------------
/modules/postback.py:
--------------------------------------------------------------------------------
1 | from templates import TextTemplate
2 | from utilities import send_help, send_message, send_newchat_prompt
3 | from endChat import endChat, share_profile
4 | from interrupts import Interrupts
5 | import json
6 |
7 | valid_payloads = [
8 | "restart",
9 | "help",
10 | "quit",
11 | "exit",
12 | "getstarted"
13 | ]
14 |
15 | interrupts = Interrupts()
16 |
17 | def handle_postback(payload, sender):
18 |
19 | if payload not in valid_payloads and json.loads(payload)["keyword"] not in valid_payloads:
20 | message = TextTemplate(text="Not sure if this is a valid command")
21 | send_message(message.get_message(), id=sender)
22 |
23 | elif payload == "restart":
24 | interrupts.handleCommand(command="restart", sender=sender)
25 | elif payload == "help":
26 | send_help(sender = sender)
27 | elif payload == "quit":
28 | interrupts.handleCommand(command="quit", sender=sender)
29 | elif payload == "getstarted":
30 | print("GET STARTED DETECTED")
31 | message = TextTemplate("Hello there, a big welcome to BlindChat. Chat with people all over the "+
32 | "world anonymously. Share your profile only when you want to.\n\n"+
33 | "We are adding cool new features every single day, so keep "+
34 | "on exploring. Cheers!\n\nAnd by the way, when in need, type"+
35 | " \"help\" to see the list of available commands")
36 | send_message(message.get_message(), id=sender)
37 | send_newchat_prompt(id=sender)
38 |
--------------------------------------------------------------------------------
/templates/generic.py:
--------------------------------------------------------------------------------
1 | from copy import deepcopy as copy
2 |
3 | from button import ButtonTemplate
4 | ButtonTemplate.get_buttons = lambda self: self.template['attachment']['payload']['buttons']
5 |
6 | TITLE_CHARACTER_LIMIT = 80
7 | SUBTITLE_CHARACTER_LIMIT = 80
8 | BUTTON_TITLE_CHARACTER_LIMIT = 20
9 | BUTTON_LIMIT = 3
10 | ELEMENTS_LIMIT = 10
11 |
12 | template = {
13 | 'template_type': 'generic',
14 | 'value': {
15 | 'attachment': {
16 | 'type': 'template',
17 | 'payload': {
18 | 'template_type': 'generic',
19 | 'elements': []
20 | }
21 | }
22 | }
23 | }
24 |
25 | class GenericTemplate:
26 | def __init__(self):
27 | self.template = copy(template['value'])
28 | self.elements = []
29 | def add_element(self, title='', item_url='', image_url='', subtitle='', buttons=[]):
30 | element = {}
31 | element['title'] = title[:TITLE_CHARACTER_LIMIT]
32 | if item_url != '':
33 | element['item_url'] = item_url
34 | element['image_url'] = image_url
35 | if subtitle != '':
36 | element['subtitle'] = subtitle[:SUBTITLE_CHARACTER_LIMIT]
37 | for button in buttons:
38 | button['title'] = button['title'][:BUTTON_TITLE_CHARACTER_LIMIT]
39 | if len(buttons) > 0:
40 | element['buttons'] = buttons[:BUTTON_LIMIT]
41 | if len(self.elements) < ELEMENTS_LIMIT:
42 | self.elements.append(element)
43 | def get_message(self):
44 | self.template['attachment']['payload']['elements'] = self.elements
45 | return self.template
46 |
--------------------------------------------------------------------------------
/modules/campaign.py:
--------------------------------------------------------------------------------
1 | from models import User
2 | from templates import TextTemplate
3 | from utilities import send_message
4 |
5 | def send_campaign():
6 | message = TextTemplate(text="NEW FEATURE: SUBSCRIPTIONS \n\n"+
7 | "Hi there, this week a new feature is coming out and that is SUBSCRIPTIONS.\n\n"+
8 | "How it works: When someone gets into the Waiting List due to non availability of "+
9 | "partners, we will send out a message to our subscribed users. For example, if you "+
10 | "subscribe for women, we will notify you when a woman is looking for a partner even "+
11 | "when you are not active and hence you'll gain the chance to chat if you are free. \n\n"+
12 | "The feature will be made available to every user after one month but some users will "+
13 | "be given access to it within 1-2 days. To be eligible for getting access, LIKE our "+
14 | "page and leave a REVIEW on our page within 36 hours. Just to emphasize, please "+
15 | "complete both to be eligible. \n\nIf you have any question, post it on our page. "+
16 | "We'll guide you, but make it within the 36 hours because after that, the feature will be out.")
17 | print("IN CAMPAIGN")
18 | message = TextTemplate(text="FUCKING TEST")
19 | #users = User.query.all()
20 | #for user in users:
21 | # id = user.id
22 | #send_message(message, id=id)
23 | users = ["1708022462556195", "1145959985508112"]
24 | for user in users:
25 | send_message(message, id=user)
26 |
27 |
--------------------------------------------------------------------------------
/DB_Wrappers/ActiveChats.py:
--------------------------------------------------------------------------------
1 | from models import ActiveChatsUser
2 |
3 | class ActiveChatsDB:
4 | def __init__(self, db):
5 | self.db = db
6 |
7 | def isActive(self, user):
8 | u = ActiveChatsUser.query.get(user)
9 | if u != None:
10 | return True
11 | else:
12 | return False
13 |
14 | def get_partner(self, user):
15 | user = ActiveChatsUser.query.get(user)
16 | return user.partner
17 |
18 | def create_new_chat(self, user1, user2):
19 | u1 = ActiveChatsUser(id=user1, partner=user2)
20 | u2 = ActiveChatsUser(id=user2, partner=user1)
21 |
22 | try:
23 | self.db.session.add(u1)
24 | except:
25 | self.db.session.delete(u1)
26 | self.db.session.add(u1)
27 |
28 | try:
29 | self.db.session.add(u2)
30 | except:
31 | self.db.session.delete(u2)
32 | self.db.session.add(u2)
33 |
34 | self.db.session.commit()
35 |
36 | def delete_chat_entries(self, user):
37 | partner = self.get_partner(user=user)
38 | user1 = ActiveChatsUser.query.get(user)
39 | user2 = ActiveChatsUser.query.get(partner)
40 | self.db.session.delete(user1)
41 | self.db.session.delete(user2)
42 | self.db.session.commit()
43 |
44 | def get_alias(self, user):
45 | u = ActiveChatsUser.query.get(user)
46 | return u.alias
47 |
48 | def set_alias(self, user, alias):
49 | u = ActiveChatsUser.query.get(user)
50 | u.alias = alias
51 | self.db.session.commit()
52 |
53 | def clear_data(self, user):
54 | user = ActiveChatsUser.query.get(user)
55 | if user != None:
56 | self.db.session.delete(user)
57 | self.db.session.commit()
--------------------------------------------------------------------------------
/modules/critical_operations.py:
--------------------------------------------------------------------------------
1 | from app import waitlistdb, activechatsdb
2 | from templates import TextTemplate
3 | from utilities import send_message, show_typing, send_newchat_prompt
4 | from endChat import endChat
5 |
6 | def restart_bot(id):
7 | show_typing(id=id, duration=1)
8 | print("here")
9 | if activechatsdb.isActive(id):
10 | print("ACTIVE", id)
11 | partner = activechatsdb.get_partner(id)
12 | activechatsdb.delete_chat_entries(id)
13 | message = TextTemplate(text="Your active chat has been ended.")
14 | send_message(message=message.get_message(), id=id)
15 | message = TextTemplate(text="Your active chat has been ended from the other side.")
16 | send_message(message=message.get_message(), id=partner)
17 |
18 | show_typing(id=partner, duration=1)
19 | send_newchat_prompt(id=partner)
20 |
21 |
22 | if waitlistdb.isWaiting(id):
23 | waitlistdb.delist(id)
24 | message = TextTemplate(text="You have been removed from the waitlist")
25 | send_message(message=message.get_message(), id=id)
26 |
27 | show_typing(id=id, duration=1)
28 | send_newchat_prompt(id=id)
29 |
30 |
31 | def execute_exit(id):
32 | show_typing(id=id, duration=1)
33 | print("EXECUTING EXIT")
34 |
35 | if activechatsdb.isActive(id):
36 | endChat(id)
37 |
38 | elif waitlistdb.isWaiting(id):
39 | waitlistdb.delist(id)
40 | message = TextTemplate(text="You have been removed from the waitlist")
41 | send_message(message=message.get_message(), id=id)
42 |
43 | show_typing(id=id, duration=1)
44 | send_newchat_prompt(id=id)
45 |
46 | else:
47 | message = TextTemplate(text="You are not in an active chat or in the waitlist. Type \"start\" to start a new chat")
48 | send_message(message=message.get_message(), id=id)
49 |
50 |
51 |
--------------------------------------------------------------------------------
/modules/setup.py:
--------------------------------------------------------------------------------
1 | import requests
2 | import config
3 | import os
4 |
5 | ACCESS_TOKEN = os.environ.get('ACCESS_TOKEN', config.ACCESS_TOKEN)
6 | APP_URL = os.environ.get('APP_URL', config.APP_URL)
7 | URL = "https://graph.facebook.com/v2.6/me/messenger_profile"
8 |
9 |
10 | def setup_menu():
11 |
12 | data = {
13 | "persistent_menu":[
14 | {
15 | "locale":"default",
16 | "call_to_actions":[
17 | {
18 | "title": "Help",
19 | "type": "postback",
20 | "payload": "help"
21 | },
22 | {
23 | "title": "Quit Chat",
24 | "type": "postback",
25 | "payload": "quit"
26 | },
27 | {
28 | "title": "Restart Bot",
29 | "type": "postback",
30 | "payload": "restart"
31 | }
32 | ]
33 | }
34 | ]
35 | }
36 | r = requests.post(url=URL, params={'access_token': ACCESS_TOKEN},
37 | json=data)
38 |
39 | def setup_getStarted():
40 | data = {
41 | "get_started":{
42 | "payload": "getstarted"
43 | }
44 | }
45 | r = requests.post(url=URL, params={'access_token': ACCESS_TOKEN},
46 | json=data)
47 |
48 | def setup_greeting():
49 | data = {
50 | "greeting":[
51 | {
52 | "locale":"default",
53 | "text":"Get Started to chat anonymously"
54 | }
55 | ]
56 | }
57 | r = requests.post(url=URL, params={'access_token': ACCESS_TOKEN},
58 | json=data)
59 |
60 | def setup_whitelist():
61 | data = {
62 | "whitelisted_domains":[
63 | APP_URL
64 | ]
65 | }
66 | r = requests.post(url=URL, params={'access_token': ACCESS_TOKEN},
67 | json=data)
68 |
69 | def setup_all():
70 | setup_menu()
71 | setup_getStarted()
72 | setup_greeting()
73 | setup_whitelist()
--------------------------------------------------------------------------------
/modules/debug.py:
--------------------------------------------------------------------------------
1 | from models import User, WaitingListUser, ActiveChatsUser, db
2 | from campaign import send_campaign
3 | from utilities import send_message
4 | from templates import TextTemplate
5 | import os
6 | import config
7 |
8 | APP_URL = os.environ.get('APP_URL', config.APP_URL)
9 |
10 | def log_waitlisted_users():
11 | waitlist = WaitingListUser.query.all()
12 | i=0
13 | print("WAITLIST IS BELOW")
14 | try:
15 | for user in waitlist:
16 | id = user.id
17 | u = User.query.get(id)
18 | print(i, u.name, user.gender, user.interest)
19 | i = i+1
20 | except Exception, e:
21 | print("LOG WAITLIST ERROR", e)
22 |
23 | def update_users():
24 | for u in User.query.all():
25 | u.status = False
26 | u.messages = ""
27 | db.session.commit()
28 |
29 | def send_emoticon(id):
30 | happy = u'\u2B50'
31 | print("EMOTICON")
32 | message = TextTemplate(text="Hi "+happy)
33 | send_message(message.get_message(), id=id)
34 | print("EMOTICON 1")
35 |
36 | def handle_debug(text, id):
37 | if text[3:] == "waitlist":
38 | log_waitlisted_users()
39 | elif text[3:] == "update":
40 | update_users()
41 | elif text[3:] == "campaign":
42 | send_campaign()
43 | elif text[3:] == "emoticon":
44 | send_emoticon(id)
45 | elif text[3:] == "webview":
46 | message = {
47 | "attachment":{
48 | "type":"template",
49 | "payload":{
50 | "template_type":"button",
51 | "text":"Test Webview?",
52 | "buttons":[
53 | {
54 | "type":"web_url",
55 | "url":APP_URL+"webview/",
56 | "title":"Show page",
57 | "webview_height_ratio": "compact"
58 | }
59 | ]
60 | }
61 | }
62 | }
63 | send_message(message=message, id=id)
64 |
65 |
66 |
--------------------------------------------------------------------------------
/models.py:
--------------------------------------------------------------------------------
1 | from app import db
2 |
3 |
4 | class User(db.Model):
5 | id = db.Column(db.String(64), primary_key=True)
6 | name = db.Column(db.String(64))
7 | gender = db.Column(db.String(10))
8 | first_name = db.Column(db.String(64))
9 | pic_url = db.Column(db.String(250))
10 | status = db.Column(db.Boolean) # pause status-- True if messages are paused, may be at a quick reply
11 | messages = db.Column(db.String(2000)) # upto two messages stored while convo is paused
12 | subscription = db.Column(db.String(10))
13 | interests = db.Column(db.String(100))
14 | bio = db.Column(db.String(100))
15 | level = db.Column(db.Integer)
16 |
17 | def __init__(self, id):
18 | self.id = id
19 | self.status = False
20 | self.messages = ""
21 |
22 | def add_details(self, name, first_name, gender, pic_url):
23 | if name is not None:
24 | self.name = name
25 | if gender is not None:
26 | self.gender = gender
27 | if first_name is not None:
28 | self.first_name = first_name
29 | if pic_url is not None:
30 | self.pic_url = pic_url
31 |
32 | def setStatus(self, status):
33 | self.status = status
34 |
35 | def getStatus(self):
36 | return self.status
37 |
38 | def __repr__(self):
39 | return '' % (self.nickname)
40 |
41 |
42 |
43 | class WaitingListUser(db.Model):
44 | id = db.Column(db.String(64), primary_key=True)
45 | gender = db.Column(db.String(10))
46 | interest = db.Column(db.String(10))
47 |
48 | def __init__(self, id, gender, interest):
49 | self.id = id
50 | self.gender = gender
51 | self.interest = interest
52 |
53 | class ActiveChatsUser(db.Model):
54 | id = db.Column(db.String(64), primary_key=True)
55 | partner = db.Column(db.String(64))
56 | alias = db.Column(db.String(80))
57 |
58 | def __init__(self, id, partner):
59 | self.id = id
60 | self.partner = partner
61 |
62 | def add_alias(self, alias):
63 | self.alias = alias
64 |
--------------------------------------------------------------------------------
/modules/gamification.py:
--------------------------------------------------------------------------------
1 | from templates import TextTemplate
2 | from utilities import send_message
3 | from app import usersdb
4 |
5 | class Game:
6 | def __init__(self, db):
7 | self.db = db
8 | self.hints = ["All is fair in ____ and war", "Hello in Spanish", "Yes in French", "How to train your _____", "Tom Marvolo Riddle <<>> I am Lord _________"]
9 | self.ans = ["love", "hola", "oui", "dragon", "voldemort"]
10 | self.valid_words = ["hint", "hints"]+self.ans
11 |
12 | def isGame(self, event):
13 | if 'message' in event and 'text' in event['message']:
14 | text = event['message']['text']
15 | text = text.lower().replace(" ", "")
16 | print("STOP THIS ALREADY", text, self.valid_words)
17 | if text in self.valid_words:
18 | print("returning ")
19 | return True
20 | return False
21 |
22 | def send_hint(self, level, id):
23 | print("game 1.5", level)
24 | message = TextTemplate(text=self.hints[level])
25 | send_message(message=message.get_message(), id=id)
26 |
27 | def upgrade_level(self, id):
28 | print("game upgrade")
29 | user = usersdb.get(id)
30 | if user.level == None:
31 | user.level = 0
32 | user.level = user.level+1
33 | self.db.session.commit()
34 | message = TextTemplate(text="Congrats! You have guessed the correct word. You are now at " + \
35 | "level "+str(user.level)+".")
36 | send_message(message.get_message(), id)
37 | if user.level!=5:
38 | message = TextTemplate(text="Here is your hint for the next level:\n\n"+self.hints[user.level])
39 | send_message(message.get_message(), id)
40 |
41 | def gamify(self, command, id):
42 | try:
43 | command = command.lower().replace(" ", "")
44 | u_level = usersdb.get(id).level
45 | print("U_LEVEL", u_level)
46 | if u_level == None:
47 | u_level = 0
48 | print("game 1", command)
49 | if command == "hint" or command == "hints":
50 | print("game 2")
51 | self.send_hint(u_level, id)
52 | return True
53 | else:
54 | a_level = self.ans.index(command)
55 | print("game 3", a_level)
56 | if a_level - u_level == 0:
57 | self.upgrade_level(id)
58 | return True
59 | else:
60 | return False
61 | except Exception, e:
62 | print("GAME ERROR", str(e))
63 |
--------------------------------------------------------------------------------
/modules/subscription.py:
--------------------------------------------------------------------------------
1 | from templates import TextTemplate, add_quick_reply
2 | import json
3 | from utilities import send_message
4 | from app import usersdb
5 |
6 |
7 | def send_subscription_prompt(id):
8 | message = TextTemplate(text="Subscribe to our notifications? We'll send out a message to you "+
9 | "when someone of your choice is looking for a partner to chat with. Sounds good?").get_message()
10 | replies = [
11 | {
12 | "title": "Yes. Subscribe",
13 | "payload": json.dumps({"keyword": "subscribe", "ans": "y"})
14 | },
15 | {
16 | "title": "No, thanks",
17 | "payload": json.dumps({"keyword": "subscribe", "ans": "n"})
18 | },
19 | {
20 | "title": "Don't show this",
21 | "payload": json.dumps({"keyword": "subscribe", "ans": "x"})
22 | }
23 | ]
24 | message = add_quick_reply(message, title=replies[0]["title"], payload=replies[0]["payload"])
25 | message = add_quick_reply(message, title=replies[1]["title"], payload=replies[1]["payload"])
26 | message = add_quick_reply(message, title=replies[2]["title"], payload=replies[2]["payload"])
27 |
28 | send_message(message,id)
29 |
30 | def send_pref_prompt(id):
31 | message = TextTemplate(text="Whom do you want to chat with? We will notify when someone of the selected gender is waiting to chat.").get_message()
32 | replies = [
33 | {
34 | "title": "Men",
35 | "payload": json.dumps({"keyword": "subscribe", "ans": "male"})
36 | },
37 | {
38 | "title": "Women",
39 | "payload": json.dumps({"keyword": "subscribe", "ans": "female"})
40 | }
41 | ]
42 | message = add_quick_reply(message, title=replies[0]["title"], payload=replies[0]["payload"])
43 | message = add_quick_reply(message, title=replies[1]["title"], payload=replies[1]["payload"])
44 | send_message(message,id)
45 |
46 | def handle_subscribe_payload(id, payload):
47 | print("inside this")
48 | if payload["ans"] == "male" or payload["ans"] == "female":
49 | usersdb.subscribe(id, pref=payload["ans"])
50 | message = TextTemplate(text="You are subscribed. We will notify you. Promise.").get_message()
51 | send_message(message, id)
52 |
53 | elif payload["ans"] == "y":
54 | send_pref_prompt(id)
55 |
56 | elif payload["ans"] == "n":
57 | message = TextTemplate(text="Okay. You can find the option to subscribe in the menu if you change your mind.").get_message()
58 | send_message(message, id)
59 |
60 | elif payload["ans"] == "x":
61 | usersdb.setSubsValue(id, val="x")
62 | message = TextTemplate(text="Alright. In case you change your mind later on, the option to subscribe is in the menu.").get_message()
63 | send_message(message, id)
64 |
--------------------------------------------------------------------------------
/DB_Wrappers/Users.py:
--------------------------------------------------------------------------------
1 | import os
2 | import config
3 | import requests
4 | from models import User
5 |
6 | class UsersDB:
7 | def __init__(self, db):
8 | self.db = db
9 |
10 | def hasDataOf(self, id):
11 | u = User.query.get(id)
12 | if u is None:
13 | return False
14 | return True
15 |
16 | def add(self, id):
17 | r = requests.get('https://graph.facebook.com/v2.6/' + str(id), params={
18 | 'fields': 'first_name,last_name,gender,profile_pic',
19 | 'access_token': os.environ.get('ACCESS_TOKEN', config.ACCESS_TOKEN)
20 | })
21 | data = r.json()
22 | try:
23 | first_name = data["first_name"]
24 | except:
25 | first_name = ""
26 |
27 | try:
28 | last_name = data["last_name"]
29 | except:
30 | last_name = ""
31 |
32 | try:
33 | gender = data["gender"]
34 | except:
35 | gender = "male"
36 |
37 | name = first_name + " " + last_name
38 | user = User(id=id)
39 | user.add_details(name=name, first_name=data["first_name"], gender=gender, pic_url=data["profile_pic"])
40 | self.db.session.add(user)
41 | self.db.session.commit()
42 |
43 | def get(self, id):
44 | user = User.query.get(id)
45 | return user
46 |
47 | def getPauseStatus(self, id):
48 | user = User.query.get(id)
49 | return user.status
50 |
51 | def setPauseStatus(self, id, status):
52 | user = User.query.get(id)
53 | user.status = status
54 | self.db.session.commit()
55 |
56 | def addMessage(self, id, message):
57 | user = User.query.get(id)
58 | m = user.messages
59 | if m == None or m == "":
60 | user.messages = message
61 | elif len(m.split('#')) == 1:
62 | user.messages = m + "#" + message
63 |
64 | self.db.session.commit()
65 |
66 | def getMessages(self, id):
67 | user = User.query.get(id)
68 | m = user.messages
69 | if m == "":
70 | return None
71 |
72 | user.messages = ""
73 | self.db.session.commit()
74 |
75 | return m.split("#")
76 |
77 | def subscribe(self, id, pref):
78 | user = User.query.get(id)
79 | user.subscription = pref
80 | self.db.session.commit()
81 |
82 | def unsubscribe(self, id):
83 | user = User.query.get(id)
84 | user.subscription = None
85 | self.db.session.commit()
86 |
87 | def getSubsValue(self, id):
88 | user = User.query.get(id)
89 | return user.subscription
90 |
91 | def setSubsValue(self, id, val):
92 | user = User.query.get(id)
93 | user.subscription = val
94 | self.db.session.commit()
95 |
96 | def setLevel(self, id, level):
97 | user = User.query.get(id)
98 | user.level = level
99 | self.db.session.commit()
--------------------------------------------------------------------------------
/templates/profile.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | Profile
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
52 |
53 |
54 |
86 |
87 |
88 | -->
89 |
90 |
91 |
--------------------------------------------------------------------------------
/templates/receipt.py:
--------------------------------------------------------------------------------
1 | from copy import deepcopy as copy
2 |
3 | template = {
4 | 'template_type': 'receipt',
5 | 'value': {
6 | 'attachment': {
7 | 'type': 'template',
8 | 'payload': {
9 | 'template_type': 'receipt',
10 | 'recipient_name': '',
11 | 'order_number': '',
12 | 'currency': '',
13 | 'payment_method': ''
14 | }
15 | }
16 | }
17 | }
18 |
19 | class ReceiptTemplate:
20 | def __init__(self, recipient_name='', order_number='', currency='', payment_method='', timestamp='', order_url=''):
21 | self.template = copy(template['value'])
22 | self.template['attachment']['payload']['recipient_name'] = recipient_name
23 | self.template['attachment']['payload']['order_number'] = order_number
24 | self.template['attachment']['payload']['currency'] = currency
25 | self.template['attachment']['payload']['payment_method'] = payment_method
26 | if timestamp != '':
27 | self.template['attachment']['payload']['timestamp'] = timestamp
28 | if order_url != '':
29 | self.template['attachment']['payload']['order_url'] = order_url
30 | self.elements = []
31 | self.address = {}
32 | self.summary = {}
33 | self.adjustments = []
34 | def add_element(self, title='', subtitle='', quantity=-1, price=0, currency='', image_url=''):
35 | element = {}
36 | element['title'] = title
37 | if subtitle != '':
38 | element['subtitle'] = subtitle
39 | if quantity != -1:
40 | element['quantity'] = quantity
41 | element['price'] = price
42 | if currency != '':
43 | element['currency'] = currency
44 | if image_url != '':
45 | element['image_url'] = image_url
46 | self.elements.append(element)
47 | def set_address(self, street_1='', street_2='', city='', postal_code='', state='', country=''):
48 | self.address['street_1'] = street_1
49 | if street_2 != '':
50 | self.address['street_2'] = street_2
51 | self.address['city'] = city
52 | self.address['postal_code'] = postal_code
53 | self.address['state'] = state
54 | self.address['country'] = country
55 | def set_summary(self, subtotal=-1, shipping_cost=-1, total_tax=-1, total_cost=0):
56 | if subtotal != -1:
57 | self.summary['subtotal'] = subtotal
58 | if shipping_cost != -1:
59 | self.summary['shipping_cost'] = shipping_cost
60 | if total_tax != -1:
61 | self.summary['total_tax'] = total_tax
62 | self.summary['total_cost'] = total_cost
63 | def add_adjustment(self, name='', amount=0):
64 | adjustment = {}
65 | adjustment['name'] = name
66 | adjustment['amount'] = amount
67 | self.adjustments.append(adjustment)
68 | def get_message(self):
69 | self.template['attachment']['payload']['elements'] = self.elements
70 | if self.address != {}:
71 | self.template['attachment']['payload']['address'] = self.address
72 | self.template['attachment']['payload']['summary'] = self.summary
73 | if self.adjustments != []:
74 | self.template['attachment']['payload']['adjustments'] = self.adjustments
75 | return self.template
76 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # BlindChat
2 |
3 | A Facebook messenger bot that allows users to chat with other people on Facebook anonymously.
4 |
5 | You can find it live [***here***](https://m.me/blindchat.go).
6 |
7 |
8 | #### NOTE: The app and the project is not maintained anymore. PRs will be unattended.
9 |
10 |
11 | ### A bit of a background
12 |
13 | I started out building BlindChat just to try out the messenger platform of Facebook and to try to build something usable out of it while learning in the process. It is more of an app rather than an AI chatbot. The outcome got a bit of traction and hence I improved certain parts of it, however, most of the code may be in an unorganized condition since those are built for quick prototyping.
14 |
15 |
16 |
17 |
18 |
19 | ### Local development / Setup your version of the app
20 |
21 | BlindChat is currently hosted on [Heroku](https://www.heroku.com/) and uses their offered database. Thus, the code and setup are written for it. If you don't want to use Heroku, you'll have to modify the code in a few places but if you are okay with Heroku, then you are just fine. It helps to have a bit of knowledge setting up a messenger bot.
22 |
23 |
24 |
25 | 1. Clone the repository by opening up your terminal/cmd and running the following command to set up your local repository:
26 | ```
27 | git clone https://github.com/mayukh18/BlindChat.git/
28 | ```
29 |
30 | 2. Create a messenger app on Facebook. Add and configure the webhook and be certain to note down both the *Access Token* and *Verify Token*.
31 |
32 | 3. Install the *Heroku CLI toolbelt* if you don't already have it. Then create an app on Heroku by opening up your terminal/cmd and running the following command:
33 | ```
34 | heroku create yourappname
35 | ```
36 |
37 | 4. Run the following command to install the required libraries to your local environment:
38 | ```
39 | pip install -r requirements.txt
40 | ```
41 |
42 | 5. Run the following command to set up a Postgres database with Heroku:
43 | ```
44 | heroku addons:add heroku-postgresql:hobby-dev
45 | ```
46 | - For more information, refer to the [official guide from Heroku](https://devcenter.heroku.com/articles/heroku-postgresql#set-up-postgres-on-windows) on setting up a Postgres database. You'll find it pretty helpful.
47 |
48 | 6. Next run the following lines:
49 | ```
50 | heroku run python
51 | >> import os
52 | >> os.environ.get('DATABASE_URL')
53 | ```
54 | - The URL returned from running the above commands is your *SQLALCHEMY_DATABASE_URI*.
55 |
56 | 7. Open the **config.py** file and replace `'YOUR_FACEBOOK_APP_ACCESS_TOKEN'` and `'FACEBOOK_APP_VERIFY_TOKEN'` with the respective tokens from Step 2, replace `'APP_URL'` with your Heroku app URL `https://yourappname.herokuapp.com/` and finally, replace `'YOUR_DATABASE_URI'` with your database URI from step 6..
57 |
58 | 8. Next, to set up and migrate the models into your database, run
59 | ```
60 | python manage.py db init
61 | python manage.py db migrate
62 | python manage.py db upgrade
63 | ```
64 |
65 | 9. Lastly, deploy to Heroku with the following command, and Voila!
66 | ```
67 | git push heroku master
68 | ```
69 |
70 | **Note:**
71 | - You may find [this memo](https://gist.github.com/mayukh18/2223bc8fc152631205abd7cbf1efdd41/) helpful if you run into problems while setting this up.
72 | - You *may* need to install PostgreSQL on your system if you run into some issues in the above step. Check [this](https://devcenter.heroku.com/articles/heroku-postgresql#set-up-postgres-on-windows) on the official guide.
73 |
74 |
75 |
76 | ### Directory structure
77 |
78 | - DB_Wrappers: Contains the wrapper classes for the models in the database.
79 | - modules: Contains all the functionalities from starting a chat session to sending a message.
80 | - templates: Contains different message templates and webviews.
81 |
82 |
83 |
84 | ### Contributing
85 |
86 | All contributions are welcome. Please discuss your ideas on the community first to avoid clash of others working on the same thing. A few issues are marked as "beginner friendly" which are suitable for beginners to try out.
87 |
88 | Ask in Issues if you are not sure on something. Cheers!
89 |
--------------------------------------------------------------------------------
/modules/alias.py:
--------------------------------------------------------------------------------
1 | _prefixes = [
2 | 'Aged', 'Ancient', 'Bubbly', 'Bitter', 'Black', 'Blue', 'Bold', 'Brave',
3 | 'Broad', 'Broken', 'Calm', 'Cold','Colossal', 'Cool', 'Crimson', 'Curly', 'Damp',
4 | 'Dark', 'Daring', 'Delicate', 'Falling', 'Fancy', 'Super', 'Jiggly',
5 | 'Flat', 'Fragrant', 'Frosty', 'Gentle', 'Green', 'Legendary',
6 | 'Icy', 'Jolly', 'Jumping', 'Little', 'Lively', 'Lucky', 'Lonely',
7 | 'Muddy', 'Mute', 'Noisy', 'Odd', 'Old', 'Orange', 'Polished', 'Proud',
8 | 'Purple', 'Quiet', 'Rapid', 'Red', 'Restless', 'Rough', 'Round', 'Royal', 'Shiny',
9 | 'Shy', 'Silent', 'Small', 'Snowy', 'Soft', 'Solitary', 'Sparkling', 'Spring',
10 | 'Square', 'Super', 'Sweet', 'Tight', 'Tiny', 'White', 'Wild', 'Yellow', 'Young', 'Sticky',
11 | 'Fluffy', 'Petite', 'Grumpy', 'Happy', 'Sleepy', 'Gray', 'Average', 'Hungry', 'Honorable',
12 | 'Kind', 'Lazy', 'Lethal', 'Macho', 'Massive', 'Puzzled', 'Rare', 'Spooky', 'Sassy', 'Tricky',
13 | 'Unique', 'Naive', 'Drowzy', 'Hot', 'Innocent', 'Naughty', 'Mischievous', 'Smart', 'Fun',
14 | 'Crazy', 'Shrewd', 'Basic', 'Gutsy', 'Cute', 'Drunk', 'Sober', 'Depressed', 'Slimy', 'Gross',
15 | 'Needy', 'Dark', 'Light', 'Roaring', 'Soaring', 'Noble', 'Vain', 'Terrifying', 'Scary',
16 | 'Studious', 'Huge', 'Enormous', 'Big', 'Giant', 'Great', 'Playful', 'Classy', 'Cold',
17 | 'Early', 'Deep', 'Awesome', 'Enhanced'
18 | ]
19 |
20 | _nouns_male = [
21 | 'King', 'Prince', 'Bandit', 'Hulk', 'Thor', 'Leo', 'Deadpool', 'Trump',
22 | 'Moustache', 'Arrow', 'Caspian', 'Horse', 'Frog', 'Monkey', 'Lion',
23 | 'Tiger', 'Cheetah', 'Eagle', 'Wizard', 'Hawk', 'Jack', 'Hippo' , 'Stallion' , 'Bull' , 'Buck',
24 | 'Emperor','Ram', 'Captain', 'Batman', 'Robin', 'Deathstroke', 'Cyborg', 'Wolverine', 'Spiderman',
25 | 'Flash', 'Panther', 'Daredevil', 'Ironman', 'Joker', 'Aquaman', 'Necromancer', 'Warlock', 'Magneto',
26 | 'Gambit', 'Cyclops', 'Ronin', 'Warden', 'Duke', 'Lord', 'Darth', 'Vader', 'Goku', 'Gohan', 'Broly',
27 | 'Ash', 'Antman', 'Doom', 'General', 'Snake', 'Devil', 'Sergeant', 'Detective', 'Demon', 'Birdman',
28 | 'Jarvis', 'Ultron', 'Stark', 'Lannister', 'Baratheon', 'Tully', 'Greyjoy', 'Tarth', 'Phasma',
29 | 'Sailor', 'Mufasa', 'Simba', 'Ninja', 'Swordsman', 'Don', 'Gangster', 'Superman', 'Doomsday',
30 | 'Lucifer', 'Serpent', 'Count', 'Anakin', 'Luke', 'Sherlock', 'Watson', 'House', 'Nemo'
31 | ]
32 |
33 | _nouns_female = [
34 | 'Alexa','Lili', 'Princess', 'Rihanna', 'Swift', 'Queen', 'LaserGirl', 'Mermaid',
35 | 'Butterfly', 'Batgirl', 'Madonna', 'Foxie', 'Lioness', 'Monroe', 'Eve', 'Xiry',
36 | 'Snail', 'Unicorn', 'Moon', 'Dove', 'Witch', 'Rose', 'Zebra', 'Seahorse', 'Squirrel' , 'Doe', 'Empress',
37 | 'Vixen', 'Widow', 'Supergirl', 'Storm', 'Catwoman', 'WonderWoman', 'Hawkgirl', 'Amazon', 'Mystique', 'Raven',
38 | 'Banshee', 'Enchantress', 'Ivy', 'Minx', 'Nova', 'Duchess', 'Bachelorette', 'Cat', 'Flower', 'Daisy',
39 | 'Sunflower', 'Lady', 'Mist', 'Misty', 'Superwoman', 'Gal', 'Dynamo', 'Connoisseur', 'Huntress',
40 | 'Angel', 'Goddess', 'Mystery', 'Maiden', 'Dame', 'Damsel', 'Beauty', 'Artist', 'Chick', 'Snake',
41 | 'Heroine', 'Tomboy', 'Doll', 'Spinster', 'Bride', 'Countess', 'Babe', 'Dora', 'Mistress', 'Highness',
42 | 'Ariana', 'Emma', 'Harley'
43 | ]
44 |
45 | _suffixes = [
46 | 'OfAdua', 'OfAtlantis', 'OfCimmeria', 'OfDarkWood', 'OfDune',
47 | 'OfEgypt', 'OfLalaland', 'OfMidgard', 'OfNowhere', 'OfOz', 'OfSparta',
48 | 'OfTheDesert', 'OfTheForest', 'OfTheFuture', 'OfTheIsland',
49 | 'OfTheJungle', 'OfTheLand', 'OfTheSea','OfTheWorld', 'TheAgeless',
50 | 'TheBabyface', 'TheBarbarian', 'TheBetrayer', 'TheBrave',
51 | 'TheDestroyer', 'TheGhost', 'TheGreat', 'TheHammer', 'TheLionheart',
52 | 'TheOld', 'TheQuiet', 'TheSecond', 'TheShadow', 'TheTall',
53 | 'TheTemplar', 'TheTraveler', 'TheWanderer', 'TheWeakest', 'TheWise',
54 | 'UnderThePass', 'ofTheBay', 'ofTheDay', 'ofTheNight'
55 | ]
56 |
57 | import random
58 |
59 |
60 | def generate_alias(gender):
61 | noun = ""
62 | prefix = ""
63 | suffix = ""
64 | if gender == "male":
65 | noun = random.choice(_nouns_male)
66 | else:
67 | noun = random.choice(_nouns_female)
68 | if _toss_a_coin():
69 | prefix = random.choice(_prefixes)
70 | else:
71 | suffix = random.choice(_suffixes)
72 | return '{0}{1}{2}'.format(prefix, noun, suffix)
73 |
74 |
75 | def _toss_a_coin():
76 | return random.randint(0, 1) == 0
77 |
--------------------------------------------------------------------------------
/modules/startChat.py:
--------------------------------------------------------------------------------
1 | from utilities import send_message
2 | from alias import generate_alias
3 | from templates import TextTemplate, GenericTemplate, AttachmentTemplate
4 | from app import waitlistdb, activechatsdb, usersdb
5 | from debug import log_waitlisted_users
6 | import os
7 | import config
8 | APP_URL = os.environ.get('APP_URL', config.APP_URL)
9 |
10 | def startChat(sender, interest):
11 | # handles the initiation of a new chat after the user selects the interest
12 | print("START1", log_waitlisted_users())
13 |
14 | try:
15 | gender = usersdb.get(sender).gender # gets the gender from the
16 | except Exception, e:
17 | gender = "male"
18 | print("ERROR #0001", str(e))
19 | try:
20 | # returns the PSID of the match
21 | match = waitlistdb.get_match(gender, interest)
22 | print("START2", match)
23 | except Exception, e:
24 | print("ERROR #0002", str(e))
25 |
26 | if match == None:
27 | try:
28 | waitlistdb.delist(id=sender) # delist because there's no guarantee that it already isn't there
29 | waitlistdb.enlist(id=sender, gender=gender, interest=interest)
30 | except Exception, e:
31 | print("ERROR #0003", str(e))
32 | message = TextTemplate(text="No match found right now. You are in the wait list. We will match you as soon"+\
33 | " as someone becomes available")
34 | send_message(message.get_message(), id=sender)
35 |
36 | else:
37 | match_gender = usersdb.get(match).gender
38 | alias1 = generate_alias(gender=gender)
39 | alias2 = generate_alias(gender=match_gender)
40 | try:
41 | activechatsdb.clear_data(user=sender)
42 | activechatsdb.clear_data(user=match)
43 | activechatsdb.create_new_chat(user1=sender, user2=match)
44 | activechatsdb.set_alias(user=sender, alias=alias1)
45 | activechatsdb.set_alias(user=match, alias=alias2)
46 | except Exception, e:
47 | print("ERROR #0004", str(e))
48 |
49 |
50 | imurl = APP_URL+"static/startchat.jpg/"
51 |
52 | # ------------------------------------ MATCH ---------------------------------------- #
53 |
54 | #message = AttachmentTemplate(url=get_start_hi(gender=gender),type="image")
55 | #send_message(message.get_message(), id=match)
56 |
57 | sender_bio = usersdb.get(sender).bio
58 | if sender_bio is None:
59 | bio = "No bio"
60 | else:
61 | bio = "Bio: " + sender_bio
62 | sender_interests = usersdb.get(sender).interests
63 | if sender_interests is None:
64 | intr = "No interests."
65 | else:
66 | intr = "Interests: " + sender_interests
67 |
68 | sender_level = usersdb.get(sender).level
69 | if sender_level == None:
70 | usersdb.setLevel(sender, 0)
71 | sender_level = usersdb.get(sender).level
72 |
73 | level_str = u'\u2B50'
74 | for i in range(sender_level):
75 | level_str = level_str + u'\u2B50'
76 |
77 | message = GenericTemplate()
78 | message.add_element(title="You are matched with "+alias1, subtitle=level_str, image_url=imurl)
79 | send_message(message=message.get_message(), id=match)
80 | message = TextTemplate(text=bio + " | "+ intr)
81 | send_message(message.get_message(), id=match)
82 |
83 | # ------------------------------------- SENDER -------------------------------------------- #
84 |
85 | #message = AttachmentTemplate(url=get_start_hi(gender=match_gender), type="image")
86 | #send_message(message.get_message(), id=sender)
87 |
88 | match_bio = usersdb.get(match).bio
89 | if match_bio is None:
90 | bio = "No bio"
91 | else:
92 | bio = "Bio: " + match_bio
93 |
94 | match_interests = usersdb.get(match).interests
95 | if match_interests is None:
96 | intr = "No interests."
97 | else:
98 | intr = "Interests: " + match_interests
99 |
100 | match_level = usersdb.get(match).level
101 | if match_level == None:
102 | usersdb.setLevel(match, 0)
103 | match_level = usersdb.get(match).level
104 |
105 | level_str = u'\u2B50'
106 | for i in range(match_level):
107 | level_str = level_str + u'\u2B50'
108 |
109 | message = GenericTemplate()
110 | message.add_element(title="You are matched with " + alias2, subtitle=level_str, image_url=imurl)
111 | send_message(message=message.get_message(), id=sender)
112 | message = TextTemplate(text=bio + " | " + intr)
113 | send_message(message.get_message(), id=sender)
114 |
115 |
116 |
--------------------------------------------------------------------------------
/modules/utilities.py:
--------------------------------------------------------------------------------
1 | from templates import TextTemplate, add_quick_reply
2 | import requests
3 | import config
4 | import os
5 | import json
6 | from app import usersdb
7 |
8 | ACCESS_TOKEN = os.environ.get('ACCESS_TOKEN', config.ACCESS_TOKEN)
9 | APP_URL = os.environ.get('APP_URL', config.APP_URL)
10 |
11 | def send_interest_menu(sender):
12 | out = {"keyword":"interest"}
13 | message = TextTemplate(text="Whom do you want to chat with?").get_message()
14 | out["interest"] = "male"
15 | message = add_quick_reply(message=message, title="Men", payload=json.dumps(out))
16 | out["interest"] = "female"
17 | message = add_quick_reply(message=message, title="Women", payload=json.dumps(out))
18 | out["interest"] = "random"
19 | message = add_quick_reply(message=message, title="Random", payload=json.dumps(out))
20 |
21 | send_message(message, sender)
22 |
23 |
24 | def send_newchat_prompt(id):
25 | payload = {"keyword": "newchat"}
26 | payload["ans"] = "y"
27 | message = TextTemplate(text="Are you ready to start a new chat").get_message()
28 | message = add_quick_reply(message=message, title="Oh! Yes!", payload=json.dumps(payload))
29 | payload["ans"] = "n"
30 | message = add_quick_reply(message=message, title="No. Later", payload=json.dumps(payload))
31 | payload["ans"] = "p"
32 | message = add_quick_reply(message=message, title="Edit Profile", payload=json.dumps(payload))
33 | send_message(message, id)
34 |
35 | def isGreeting(text):
36 | valid = ["hi", "hello", "hey"]
37 | if text.lower() in valid:
38 | return True
39 | return False
40 |
41 | def handle_greetings(text, id, name):
42 | message = TextTemplate(text="Hi "+name+". Nice to meet you. To get a list of available commands, type \"help\"")
43 | send_message(message.get_message(), id)
44 |
45 | def send_message(message, id, pause_check=False):
46 |
47 | if isinstance(message, dict) == False:
48 | message = message.get_message()
49 | try:
50 | if pause_check and usersdb.getPauseStatus(id):
51 | print("USER PAUSED, MESSAGE STORED")
52 | usersdb.addMessage(id=id, message=json.dumps(message))
53 | return
54 | except Exception, e:
55 | print("STORAGE", str(e))
56 |
57 | try:
58 | if 'quick_replies' in message:
59 | usersdb.setPauseStatus(id=id, status=True)
60 | except:
61 | print("hoola")
62 |
63 | payload = {
64 | 'recipient': {
65 | 'id': id
66 | },
67 | 'message': message
68 | }
69 | r = requests.post('https://graph.facebook.com/v2.6/me/messages', params={'access_token': ACCESS_TOKEN},
70 | json=payload)
71 |
72 | def send_help(sender):
73 | helptext = """BlindChat allows you to chat with people without revealing your identity.
74 | The bot will match you with strangers all over the world.
75 | You can choose to share your profile with the other person after ending the chat.
76 |
77 | Available commands:
78 | quit - quits from the active chat or from the waitlist
79 | help - view the help menu
80 | start - starts to look for a new chatrestart - restart the bot
81 | profile - modify your chat profile
82 | """
83 |
84 | message = TextTemplate(text=helptext)
85 | send_message(message.get_message(), sender)
86 |
87 |
88 | def show_typing(id, duration):
89 | from time import sleep
90 | payload = {
91 | 'recipient': {
92 | 'id': id
93 | },
94 | "sender_action":"typing_on"
95 | }
96 | r = requests.post('https://graph.facebook.com/v2.6/me/messages', params={'access_token': ACCESS_TOKEN},
97 | json=payload)
98 |
99 | sleep(duration)
100 | payload["sender_action"] = "typing_off"
101 | r = requests.post('https://graph.facebook.com/v2.6/me/messages', params={'access_token': ACCESS_TOKEN},
102 | json=payload)
103 |
104 | def send_paused_messages(id):
105 | if usersdb.getPauseStatus(id) == False:
106 | m_list = usersdb.getMessages(id)
107 | print("MLIST", m_list)
108 | try:
109 | if m_list is None or len(m_list[0])==0:
110 | return
111 | except Exception, e:
112 | print("problem is here", m_list)
113 | for m in m_list:
114 | send_message(message=json.loads(m), id=id)
115 |
116 | def send_profile_prompt(id):
117 | message = {
118 | "attachment":{
119 | "type":"template",
120 | "payload":{
121 | "template_type":"button",
122 | "text":"To modify or edit your chat profile, click the PROFILE button",
123 | "buttons":[
124 | {
125 | "type":"web_url",
126 | "url":APP_URL+"webview?id="+str(id),
127 | "title":"PROFILE",
128 | "webview_height_ratio": "compact"
129 | }
130 | ]
131 | }
132 | }
133 | }
134 | send_message(message=message, id=id)
135 |
--------------------------------------------------------------------------------
/modules/endChat.py:
--------------------------------------------------------------------------------
1 | from templates import *
2 | from app import activechatsdb, usersdb
3 | from subscription import send_subscription_prompt
4 | from utilities import send_message, send_newchat_prompt, show_typing
5 | import requests
6 | import config
7 | import os
8 | import json
9 |
10 | ADMIN_ID = os.environ.get('ADMIN_ID', config.ADMIN_ID)
11 | ACCESS_TOKEN = os.environ.get('ACCESS_TOKEN', config.ACCESS_TOKEN)
12 | APP_URL = os.environ.get('APP_URL', config.APP_URL)
13 |
14 | def endChat(sender):
15 |
16 | try:
17 | partner = activechatsdb.get_partner(sender)
18 | alias1 = activechatsdb.get_alias(sender)
19 | alias2 = activechatsdb.get_alias(partner)
20 | except:
21 | message = TextTemplate(text="No open chat was found which can be closed")
22 | send_message(message.get_message(), id=sender)
23 | show_typing(id=sender, duration=2)
24 | send_newchat_prompt(id=sender)
25 | return
26 |
27 | imurl = APP_URL+"static/endchat1.jpg/"
28 |
29 | # -------------------------- SENDER --------------------------- #
30 |
31 | replies_sender = [
32 | {
33 | "title":"Share profile",
34 | "payload":json.dumps({"keyword":"profile_share","ans":"y", "alias":alias1, "partner":partner})
35 | },
36 | {
37 | "title":"Don't share",
38 | "payload":json.dumps({"keyword":"profile_share","ans":"n", "alias":alias1, "partner":partner})
39 | }
40 | ]
41 |
42 | message = GenericTemplate()
43 | title = "You have ended the chat with "+alias2
44 | subtitle = "Hope you had a nice experience."
45 | message.add_element(title=title, subtitle=subtitle, image_url=imurl)
46 | send_message(message=message.get_message(), id=sender)
47 |
48 | message = TextTemplate(text="Would you like to share your profile with "+alias2+"?").get_message()
49 | message = add_quick_reply(message, title=replies_sender[0]["title"], payload=replies_sender[0]["payload"])
50 | message = add_quick_reply(message, title=replies_sender[1]["title"], payload=replies_sender[1]["payload"])
51 | send_message(message=message, id=sender)
52 |
53 | # ----------------------------------------------------------------------- #
54 |
55 | # ------------------------------- PARTNER ------------------------------- #
56 |
57 | replies_partner = [
58 | {
59 | "title": "Share profile",
60 | "payload": json.dumps({"keyword": "profile_share", "ans": "y", "alias": alias2, "partner": sender})
61 | },
62 | {
63 | "title": "Don't share",
64 | "payload": json.dumps({"keyword": "profile_share", "ans": "n", "alias": alias2, "partner": sender})
65 | }
66 | ]
67 |
68 | message = GenericTemplate()
69 | title = alias1+" has quit the chat"
70 | subtitle = "Hope you had a nice experience while it lasted."
71 | message.add_element(title=title, subtitle=subtitle, image_url=imurl)
72 | send_message(message=message.get_message(), id=partner, pause_check=True)
73 |
74 | message = TextTemplate(text="Would you like to share your profile with " + alias1 + "?").get_message()
75 | message = add_quick_reply(message, title=replies_partner[0]["title"], payload=replies_partner[0]["payload"])
76 | message = add_quick_reply(message, title=replies_partner[1]["title"], payload=replies_partner[1]["payload"])
77 | send_message(message=message, id=partner, pause_check=True)
78 |
79 | # --------------------------------------------------------------- #
80 |
81 | try:
82 | activechatsdb.delete_chat_entries(user=sender)
83 | except Exception, e:
84 | print("ENDCHAT ERROR", str(e))
85 |
86 |
87 |
88 | def share_profile(sender, payload):
89 | if isinstance(payload, str) or isinstance(payload, unicode):
90 | payload = json.loads(str(payload))
91 | print("SHAREPROFILE PAYLOAD", payload)
92 |
93 | alias = payload["alias"]
94 | partner = payload["partner"]
95 |
96 | if payload["ans"] == "y":
97 | r = requests.get('https://graph.facebook.com/v2.6/' + str(sender), params={
98 | 'fields': 'first_name,last_name,profile_pic',
99 | 'access_token': os.environ.get('ACCESS_TOKEN', config.ACCESS_TOKEN)
100 | })
101 | userData = r.json()
102 |
103 | message = TextTemplate(text=alias + " has shared his/her profile with you")
104 | send_message(message=message.get_message(), id=partner, pause_check=True)
105 | message = GenericTemplate()
106 | message.add_element(title=userData["first_name"] + " " + userData["last_name"],image_url=userData["profile_pic"],
107 | subtitle="Search on Facebook by the name and recognise by the profile picture")
108 | send_message(message=message.get_message(), id=partner, pause_check=True)
109 |
110 | else:
111 | message = TextTemplate(text=alias + " has chosen not to share his/her profile with you")
112 | send_message(message=message.get_message(), id=partner, pause_check=True)
113 |
114 | show_typing(id=sender, duration=1)
115 | if sender != ADMIN_ID:
116 | send_newchat_prompt(id=sender)
117 | elif usersdb.getSubsValue(id=sender) != "x":
118 | send_subscription_prompt(id=sender)
119 |
120 |
--------------------------------------------------------------------------------
/app.py:
--------------------------------------------------------------------------------
1 | import os
2 | import config
3 | from flask import Flask, request, render_template
4 | from flask_sqlalchemy import SQLAlchemy
5 | from analytics import Analytics
6 |
7 | # --------------------------------------------------------------- #
8 |
9 | ACCESS_TOKEN = os.environ.get('ACCESS_TOKEN', config.ACCESS_TOKEN)
10 | VERIFY_TOKEN = os.environ.get('VERIFY_TOKEN', config.VERIFY_TOKEN)
11 | PAGE_ID = os.environ.get('PAGE_ID', config.PAGE_ID)
12 | ADMIN_ID = os.environ.get('ADMIN_ID', config.ADMIN_ID)
13 |
14 | # --------------------------------------------------------------- #
15 |
16 | app = Flask(__name__)
17 | app.config.from_object('config')
18 | db = SQLAlchemy(app)
19 |
20 | # --------------------------------------------------------------- #
21 |
22 | from models import User, WaitingListUser, ActiveChatsUser
23 | from templates import TextTemplate
24 | from DB_Wrappers import *
25 |
26 | usersdb = UsersDB(db=db)
27 | waitlistdb = WaitingListDB(db=db)
28 | activechatsdb = ActiveChatsDB(db=db)
29 |
30 | from modules import *
31 | setup_all()
32 | metrics = Analytics()
33 | Int = Interrupts()
34 | game = Game(db=db)
35 |
36 | # --------------------------------------------------------------- #
37 | @app.route('/webview/', methods=['POST'])
38 | def getProfile():
39 | try:
40 | print("FORM SUBMITTED", dict(request.form))
41 | bio = request.form['bio']
42 | interests = request.form['interests']
43 | id = request.form['psid']
44 | print("USER ID", id)
45 | user = usersdb.get(id)
46 | user.interests = interests
47 | user.bio = bio
48 | user.liked = True
49 | db.session.commit()
50 | return render_template('result.html')
51 | except Exception, e:
52 | print("FORM ERROR", str(e))
53 |
54 | @app.route('/webview/', methods=['GET'])
55 | def render():
56 | id = request.args.get('id')
57 | print("PROFILE ID", id)
58 | user = usersdb.get(id)
59 | bio = user.bio
60 | interests = user.interests
61 | level = user.level
62 | level_str = u'\u2B50'
63 | for i in range(level):
64 | level_str = level_str + u'\u2B50'
65 |
66 | if bio is None:
67 | bio = ""
68 | if interests is None:
69 | interests = ""
70 | return render_template('profile.html', id=id, bio=bio, interests=interests, level=level_str)
71 |
72 |
73 | @app.route('/webhook/', methods=['GET', 'POST'])
74 | def webhook():
75 | if request.method == 'POST':
76 | data = request.get_json(force=True)
77 |
78 | # analytics api post
79 | metrics.record(entry=data["entry"])
80 |
81 | messaging_events = data['entry'][0]['messaging']
82 | for event in messaging_events:
83 | sender = event['sender']['id']
84 | print("EVENT", event)
85 |
86 | try:
87 | if sender != PAGE_ID and usersdb.hasDataOf(sender) is False:
88 | usersdb.add(sender)
89 | except Exception, e:
90 | print("ERROR", str(e))
91 |
92 |
93 | try:
94 | if 'postback' in event and 'payload' in event['postback']:
95 | postback_payload = event['postback']['payload']
96 | print("postback payload", postback_payload)
97 | handle_postback(payload=postback_payload, sender=sender)
98 | print("postback handled")
99 | continue
100 | elif 'message' in event and 'text' in event['message']:
101 | if Int.isValidCommand(event['message']['text']):
102 | print("interrupt detected", event['message']['text'])
103 | Int.handleCommand(command=event['message']['text'], sender=sender)
104 | print("interrupt handled")
105 | continue
106 | else:
107 | print("NOT POSTBACK OR INTERRUPT")
108 | except Exception, e:
109 | print("POSTBACK/INTERRUPT ERROR", str(e))
110 | db.session.rollback()
111 | return ''
112 |
113 | if game.isGame(event) == True:
114 | x = game.gamify(event['message']['text'], id=sender)
115 | if x == True:
116 | continue
117 |
118 | if activechatsdb.isActive(sender):
119 | alias = activechatsdb.get_alias(sender)
120 | if 'message' in event and 'text' in event['message']:
121 | text = event['message']['text']
122 |
123 | if 'quick_reply' in event['message'] and 'payload' in event['message']['quick_reply']:
124 | quick_reply_payload = event['message']['quick_reply']['payload']
125 | handle_quick_reply(sender=sender, payload=quick_reply_payload)
126 |
127 | else:
128 | message = TextTemplate(text=alias+": "+text)
129 | recipient = activechatsdb.get_partner(sender)
130 | send_message(message=message.get_message(), id=recipient)
131 |
132 | elif 'message' in event and 'attachments' in event['message'] and 'type' in event['message']['attachments'][0]:
133 | if event['message']['attachments'][0]['type'] == "image":
134 | handle_image(sender=sender, url=event['message']['attachments'][0]['payload']['url'])
135 | else:
136 | recipient = sender
137 | if 'message' in event and 'text' in event['message']:
138 | text = event['message']['text']
139 |
140 | try:
141 | if text[:3] == ":::":
142 | handle_debug(text, id=sender)
143 | message = TextTemplate(text="Debug command executed")
144 | send_message(message.get_message(), id=recipient)
145 | continue
146 | except Exception, e:
147 | print("DEBUG ERROR", str(e))
148 |
149 | if 'quick_reply' in event['message'] and 'payload' in event['message']['quick_reply']:
150 | quick_reply_payload = event['message']['quick_reply']['payload']
151 | handle_quick_reply(sender=sender, payload=quick_reply_payload)
152 | else:
153 | if(isGreeting(text)):
154 | handle_greetings(text, sender, usersdb.get(sender).first_name)
155 | continue
156 | message = TextTemplate(text="I didn't understand what you intended. Type \"help\" to"+
157 | " get the set of available commands. Use those commands or"+
158 | " the menu options to interact with the bot")
159 | send_message(message.get_message(), id=recipient)
160 |
161 | return '' # 200 OK
162 |
163 | elif request.method == 'GET': # Verification
164 | if request.args.get('hub.verify_token') == VERIFY_TOKEN:
165 | return request.args.get('hub.challenge')
166 | else:
167 | return 'Error, wrong validation token'
168 |
169 |
170 | if __name__ == '__main__':
171 | app.run()
172 | #, port=int(os.environ.get('PORT', 4431))
--------------------------------------------------------------------------------