Skip to content
2 changes: 1 addition & 1 deletion Config.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,4 +12,4 @@ class Config:
log_level = int(os.environ.get('SDK_LOG_LEVEL', logging.DEBUG))
log_facility_name = os.environ.get('SDK_LOG_FACILITY_NAME', "python_bale_bot")
source = os.environ.get('LOG_SOURCE', "bot_source")
heartbeat = int(os.environ.get("HEARTBEAT",30))
heartbeat = int(os.environ.get("HEARTBEAT", 30))
1 change: 0 additions & 1 deletion balebot/bale_future.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
from asyncio import Future
import collections


Expand Down
11 changes: 6 additions & 5 deletions balebot/bot.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,9 @@


class Bot:
def __init__(self, loop, token, incoming_queue, outgoing_queue, bale_futures, timeout):
def __init__(self, loop, token, base_url, incoming_queue, outgoing_queue, bale_futures, timeout):
self._loop = loop
self.network = Network(token=token,
self.network = Network(token=token, base_url=base_url,
incoming_queue=incoming_queue,
outgoing_queue=outgoing_queue,
loop=loop)
Expand Down Expand Up @@ -81,9 +81,8 @@ def respond(self, update, message, success_callback=None, failure_callback=None,
# messaging
def send_message(self, message, peer, quoted_message=None, random_id=None, success_callback=None,
failure_callback=None, **kwargs):
receiver = peer
request_body = SendMessage(message=message, receiver_peer=receiver,
quoted_message=quoted_message, random_id=random_id)
request_body = SendMessage(message=message, receiver_user=peer, quoted_message=quoted_message,
random_id=random_id)
request = Request(service=ServiceType.Messaging, body=request_body)
self.set_future(request.id, request_body, success_callback, failure_callback, **kwargs)
self.send_request(request.get_json_str())
Expand Down Expand Up @@ -177,6 +176,7 @@ async def get_data(download_url):
future.reject(response=None)
except Exception as e:
future.reject(response=None)

url = result.body.url
asyncio.ensure_future(get_data(url))

Expand Down Expand Up @@ -221,6 +221,7 @@ async def upload_data():
future.reject(response=None)
except Exception as e:
future.reject(response=None)

asyncio.ensure_future(upload_data())

def file_upload_url_failure(result, user_data):
Expand Down
6 changes: 3 additions & 3 deletions balebot/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@


class Config:
receive_timeout = int(os.environ.get("SESSION_TIMEOUT",60))
receive_timeout = int(os.environ.get("SESSION_TIMEOUT", 60))
base_url = os.environ.get('BASE_URL', "wss://api.bale.ai/v1/bots/")
request_timeout = int(os.environ.get('REQUEST_TIMEOUT', 5))
# 0:print to output 1:use graylog 2:both 0 and 1
Expand All @@ -13,7 +13,7 @@ class Config:
graylog_port = int(os.environ.get('SDK_GRAYLOG_PORT', 12201))
log_level = int(os.environ.get('SDK_LOG_LEVEL', logging.DEBUG))
log_facility_name = os.environ.get('SDK_LOG_FACILITY_NAME', "python_bale_bot")
monitoring_hash = os.environ.get('MONITORING_HASH', "SADJSDSDas4d2asf41f2a2faasd45sas-")
monitoring_hash = os.environ.get('MONITORING_HASH', "kjs3cns6uuw7b8cgx14d2asf41f2a2fd45sp-")
real_time_fetch_updates = os.environ.get('REAL_TIME_FETCH_UPDATES', True)
continue_last_processed_seq = os.environ.get('CONTINUE_LAST_PROCESSED_SEQ', False)
timeInterval = int(os.environ.get('TIME_INTERVAL', 1)) # unit for time interval is second)
Expand All @@ -23,4 +23,4 @@ class Config:
redis_host = os.getenv('REDIS_HOST', "localhost")
redis_port = int(os.getenv('REDIS_PORT', 6379))
redis_db = os.getenv('REDIS_DB', 0)
group_shield = int(os.getenv('GROUP_SHIELD', 1))
group_shield = int(os.getenv('GROUP_SHIELD', 0))
20 changes: 13 additions & 7 deletions balebot/connection/network.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,10 @@
class Network:
""" network layer main class """

def __init__(self, token, incoming_queue=None, outgoing_queue=None, loop=None):
def __init__(self, token, base_url, incoming_queue=None, outgoing_queue=None, loop=None):

self.logger = Logger.get_logger()
self._base_url = Config.base_url
self._base_url = base_url
self._token = token
self._running = False
self._incoming_queue = incoming_queue or asyncio.Queue()
Expand All @@ -33,24 +33,30 @@ async def connect(self):

try:
self._session = aiohttp.ClientSession(loop=self._loop)
self._ws = await self._session.ws_connect(self.construct_url(),heartbeat=self._heartbeat,receive_timeout=self._receive_timeout,headers={"source":"python3.5"})
self._ws = await self._session.ws_connect(self.construct_url(), heartbeat=self._heartbeat,
receive_timeout=self._receive_timeout,
headers={"source": "python3.5"})
self.logger.warning('connect success: {}'.format(self.construct_url()))
except Exception as e:
await self.disconnect()
self.logger.error('connect error: {}'.format(e),
extra={"tag": "err","type": "connection", "url": self.construct_url(), "error_type": type(e)})
extra={"tag": "err", "type": "connection", "url": self.construct_url(),
"error_type": type(e)})
traceback.print_exc()

elif self._ws.closed:
try:
if self._session.closed:
self._session = aiohttp.ClientSession(loop=self._loop)
self._ws = await self._session.ws_connect(self.construct_url(),heartbeat=self._heartbeat,receive_timeout=self._receive_timeout,headers={"source":"python3.5"})
self._ws = await self._session.ws_connect(self.construct_url(), heartbeat=self._heartbeat,
receive_timeout=self._receive_timeout,
headers={"source": "python3.5"})
self.logger.warning('reconnect success: {}'.format(self.construct_url()))
except Exception as e:
await self.disconnect()
self.logger.error('reconnect error: {}'.format(e),
extra={"tag": "err", "type": "connection", "url": self.construct_url(), "error_type": type(e)})
extra={"tag": "err", "type": "connection", "url": self.construct_url(),
"error_type": type(e)})
traceback.print_exc()

return self._ws
Expand Down Expand Up @@ -127,4 +133,4 @@ def connected(self):
return True

def send(self, item):
self._outgoing_queue.put_nowait(item)
self._outgoing_queue.put_nowait(item)
4 changes: 2 additions & 2 deletions balebot/dispatcher.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,15 +16,15 @@


class Dispatcher:
def __init__(self, loop, token, bale_futures):
def __init__(self, loop, token, base_url, bale_futures):

self.logger = Logger.get_logger()
self.incoming_queue = asyncio.Queue()
self.outgoing_queue = asyncio.Queue()
self.timeout = Config.request_timeout
self.token = token
self.bot = Bot(loop=loop,
token=token,
token=token, base_url=base_url,
incoming_queue=self.incoming_queue,
outgoing_queue=self.outgoing_queue,
bale_futures=bale_futures,
Expand Down
6 changes: 1 addition & 5 deletions balebot/filters/contact_filter.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,4 @@

class ContactFilter(Filter):
def match(self, message):
if isinstance(message, JsonMessage):
raw_json = message.raw_json
return isinstance(raw_json, ContactMessage)
else:
return False
return isinstance(message, ContactMessage)
22 changes: 16 additions & 6 deletions balebot/filters/template_response_filter.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,18 @@


class TemplateResponseFilter(Filter):
def __init__(self, keywords=None, pattern=None, validator=None, include_commands=True):
def __init__(self, keywords=None, exact_keywords=None, pattern=None, validator=None, include_commands=True):
super(TemplateResponseFilter, self).__init__(validator)
self.keywords = []
self.exact_keywords = []
if isinstance(keywords, list):
self.keywords += keywords
elif isinstance(keywords, str):
self.keywords.append(keywords)
if isinstance(exact_keywords, list):
self.exact_keywords += exact_keywords
elif isinstance(keywords, str):
self.exact_keywords.append(exact_keywords)

self.pattern = pattern
self.validator = validator if callable(validator) else None
Expand All @@ -19,15 +24,14 @@ def __init__(self, keywords=None, pattern=None, validator=None, include_commands
def match(self, message):
if isinstance(message, TemplateResponseMessage):
text = message.text
if not self.include_commands:
if text.startswith("/"):
return False

if not self.include_commands and text.startswith("/"):
return False
if not self.pattern and not self.keywords and not self.validator:
return True

if self.find_keywords(text):
return True
elif self.find_exact_keywords(text):
return True
elif self.find_pattern(text):
return True
elif self.validate(text):
Expand All @@ -42,6 +46,12 @@ def find_keywords(self, text):
return True
return False

def find_exact_keywords(self, text):
for keyword in self.exact_keywords:
if keyword == text:
return True
return False

def find_pattern(self, text):
if self.pattern:
return re.search(self.pattern, text)
Expand Down
27 changes: 18 additions & 9 deletions balebot/filters/text_filter.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,18 @@


class TextFilter(Filter):
def __init__(self, keywords=None, pattern=None, validator=None, include_commands=True):
def __init__(self, keywords=None, exact_keywords=None, pattern=None, validator=None, include_commands=True):
super(TextFilter, self).__init__(validator)
self.keywords = []
self.exact_keywords = []
if isinstance(keywords, list):
self.keywords += keywords
elif isinstance(keywords, str):
self.keywords.append(keywords)
if isinstance(exact_keywords, list):
self.exact_keywords += exact_keywords
elif isinstance(keywords, str):
self.exact_keywords.append(exact_keywords)

self.pattern = pattern
self.validator = validator if callable(validator) else None
Expand All @@ -19,15 +24,14 @@ def __init__(self, keywords=None, pattern=None, validator=None, include_commands
def match(self, message):
if isinstance(message, TextMessage):
text = message.text
if not self.include_commands:
if text.startswith("/"):
return False

if not self.include_commands and text.startswith("/"):
return False
if not self.pattern and not self.keywords and not self.validator:
return True

if self.find_keywords(text):
return True
elif self.find_exact_keywords(text):
return True
elif self.find_pattern(text):
return True
elif self.validate(text):
Expand All @@ -37,9 +41,14 @@ def match(self, message):

def find_keywords(self, text):
for keyword in self.keywords:
if keyword:
if text.find(keyword) != -1:
return True
if keyword == text:
return True
return False

def find_exact_keywords(self, text):
for keyword in self.exact_keywords:
if keyword == text:
return True
return False

def find_pattern(self, text):
Expand Down
16 changes: 10 additions & 6 deletions balebot/models/client_requests/messaging/send_message.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,14 @@


class SendMessage(RequestBody):
def __init__(self, message, receiver_peer, quoted_message=None, random_id=None):
def __init__(self, message, receiver_user, quoted_message=None, random_id=None):

if isinstance(message, BaseMessage) and isinstance(receiver_peer, Peer) and (
isinstance(quoted_message, BotQuotedMessage) or not quoted_message):
if isinstance(message, BaseMessage) and (
isinstance(receiver_user, Peer) or isinstance(receiver_user, str)) and (
isinstance(quoted_message, BotQuotedMessage) or not quoted_message):

self.message = message
self.receiver_peer = receiver_peer
self.receiver_user = receiver_user
self.quoted_message = quoted_message

if random_id:
Expand All @@ -31,13 +32,16 @@ def get_json_object(self):

data = {
"$type": RequestType.send_message,
"peer": self.receiver_peer.get_json_object(),
"randomId": self._random_id,
"message": self.message.get_json_object(),
"quotedMessage": self.quoted_message.get_json_object() if self.quoted_message else None,
}
if isinstance(self.receiver_user, Peer):
data["peer"] = self.receiver_user.get_json_object()
else:
data["nickName"] = self.receiver_user

return data

def get_json_str(self):
return json_handler.dumps(self.get_json_object())
return json_handler.dumps(self.get_json_object())
11 changes: 8 additions & 3 deletions balebot/updater.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import asyncio
import pickle
import signal
import traceback
from collections import namedtuple

Expand All @@ -15,13 +16,16 @@


class Updater:
def __init__(self, token, loop=None):
def __init__(self, token, base_url=Config.base_url, loop=None):

self.logger = Logger.get_logger()

if not token:
raise ValueError("`token` did't passed")

if not base_url:
raise ValueError("`base_url` did't passed")

self.token = token
self.timeout = Config.request_timeout

Expand All @@ -30,18 +34,19 @@ def __init__(self, token, loop=None):
self._loop = asyncio.get_event_loop() if not loop else loop

self.dispatcher = Dispatcher(loop=self._loop,
token=self.token,
token=self.token, base_url=base_url,
bale_futures=self.bale_futures)

self.running = False

def run(self, stop_after=None):
signal.signal(signal.SIGTERM, self.stop)
if Config.state_holder:
bot_previous_state = redis_db.get(self.token)
bot_previous_state = pickle.loads(bot_previous_state) if bot_previous_state else None
self.dispatcher.conversation_next_step_handlers, self.dispatcher.conversation_data = \
(bot_previous_state.conversation_next_step_handlers, bot_previous_state.conversation_data) \
if bot_previous_state else ({}, {})
if bot_previous_state else ({}, {})

asyncio.ensure_future(self._run_dispatcher())
asyncio.ensure_future(self.dispatcher.bot.network.run())
Expand Down
Loading