List of commits:
Subject Hash Author Date (UTC)
Reverted to Python 3.4 asyncio syntax. 43f7209ba91a14f6e6ac1f9727542c2184660399 Detche 2016-12-01 15:05:40
Fixed reaction on discord reactions. 8ee16b5e61d096d1905643cec4da05e7714ed75c Detche 2016-11-29 16:41:56
Fixed log error on leave(). cde179a63badbfdfd17a345886214e1d2b0a1e54 Detche 2016-11-29 15:44:53
Bot now prints in a log file if given at initialization e13bd3dbb86d1bb6f072f751412e89d444d870f3 Detche 2016-11-29 15:38:18
Updated example. e95d1599676ae10b950b2c069e666060005627cf Detche 2016-11-13 19:52:41
Added scheduler to task core. Modified comm for new event. ed51d5d18684dabdb17675294727ad5e8b8af454 Detche 2016-11-13 19:44:05
Started adding possibility to save in database. cf28a7731335cd1ffd2ebd03cc2e890c25e1c64b Detche 2016-11-13 19:43:21
Changed db interface and users/groups models. d0fdf8873a107c44d6acbef5cbffc869461d9aab Detche 2016-11-03 15:22:10
Changed UserId from element to attribute. 5407592cba9e7488519e069927a8ffb9ed32fdf6 Detche 2016-11-02 15:02:30
Added tasks system. 13bbf9857a0a61d5e2b0fd9483f5efd235cbd4f2 Detche 2016-11-02 14:58:20
Modified Knowledge process. Fixed indent 28e52095a297cbb0e6b9b6d799bb80ebe52828c1 Detche 2016-10-23 12:11:30
Updated README 8e298151286ec3cb4df29633aaca90fc871f2e80 Detche 2016-10-23 10:10:45
Update README.rst 7965df28cbef557fd3819919b4d44f0733dcecf0 Guillaume 2016-10-23 00:06:05
Added README page 8339ac5b13803b026dbfc5edd77fa50a24a70ecb Detche 2016-10-22 23:47:05
Added comments to sources. ce6491ef1337ea34d33b7e4ede0eb9f634e7ab1a Detche 2016-10-22 23:32:26
Added examples. Modified reaction class to add triggers. 545a35d1c5bb36e1b4e4d818b0e6a8f6642a222f Detche 2016-10-22 20:56:54
Initial commit 2cd79df6224290a994b1453f0327740816b0f632 Detche 2016-10-21 16:21:02
Commit 43f7209ba91a14f6e6ac1f9727542c2184660399 - Reverted to Python 3.4 asyncio syntax.
Author: Detche
Author date (UTC): 2016-12-01 15:05
Committer name: Detche
Committer date (UTC): 2016-12-01 15:05
Parent(s): 8ee16b5e61d096d1905643cec4da05e7714ed75c
Signer:
Signing key:
Signing status: N
Tree: 3e070dc73f7dae6b170cce6ca321a85ef1c7fa83
File Lines added Lines deleted
botly/bot.py 9 6
botly/comm.py 27 19
botly/reaction.py 8 5
botly/task.py 10 7
examplebot/reactions/EMPTY.py.example 2 1
examplebot/reactions/HELP.py.example 4 3
examplebot/reactions/sayhi.py 5 4
File botly/bot.py changed (mode: 100644) (index 49c7c04..6ae811d)
... ... class Bot:
62 62 else: else:
63 63 print(m) print(m)
64 64
65 async def leave(self):
65 @asyncio.coroutine
66 def leave(self):
66 67 """Coroutine that disconnects the robot from Discord.""" """Coroutine that disconnects the robot from Discord."""
67 await self.comm.logout()
68 yield from self.comm.logout()
68 69
69 async def say(self, channel, message):
70 @asyncio.coroutine
71 def say(self, channel, message):
70 72 """Coroutine that send a message to discord.""" """Coroutine that send a message to discord."""
71 await self.comm.send_message(channel, message)
73 yield from self.comm.send_message(channel, message)
72 74
73 75 def set_bot_info(self, user, server): def set_bot_info(self, user, server):
74 76 """This will be called once the bot is connected to Discord.""" """This will be called once the bot is connected to Discord."""
75 77 self.me = user self.me = user
76 78 self.server = server self.server = server
77 79
78 async def react_to(self, eventName, **eventInfo):
80 @asyncio.coroutine
81 def react_to(self, eventName, **eventInfo):
79 82 """Coroutine that will be called upon events. Checks for triggers.""" """Coroutine that will be called upon events. Checks for triggers."""
80 83 reactions = self.behaviour.get_reactions(eventName) reactions = self.behaviour.get_reactions(eventName)
81 84 if reactions: if reactions:
82 85 for reaction in reactions: for reaction in reactions:
83 86 if reaction.trigger.is_triggered(self, **eventInfo): if reaction.trigger.is_triggered(self, **eventInfo):
84 87 reaction.prepare_react(**eventInfo) reaction.prepare_react(**eventInfo)
85 await reaction.react()
88 yield from reaction.react()
86 89
87 90
88 91
File botly/comm.py changed (mode: 100644) (index 069710f..e1adc16)
... ... class Comm(discord.Client):
13 13 self.bot = bot self.bot = bot
14 14 super(Comm, self).__init__(max_messages=bot.settings.get_int( super(Comm, self).__init__(max_messages=bot.settings.get_int(
15 15 'CacheMaxMessages')) 'CacheMaxMessages'))
16
17 async def on_ready(self):
16
17 @asyncio.coroutine
18 def on_ready(self):
18 19 self.bot.print('Bot ready.') self.bot.print('Bot ready.')
19 20 server = None server = None
20 21 for s in self.servers: for s in self.servers:
21 22 server = s server = s
22 23 self.bot.set_bot_info(self.user, server) self.bot.set_bot_info(self.user, server)
23 await self.bot.react_to('on_ready')
24 yield from self.bot.react_to('on_ready')
24 25
25 async def on_typing(self, channel, user, when):
26 @asyncio.coroutine
27 def on_typing(self, channel, user, when):
26 28 if user != self.user: if user != self.user:
27 await self.bot.react_to('on_typing', channel=channel, user=user,
28 when=when)
29 yield from self.bot.react_to('on_typing', channel=channel,
30 user=user, when=when)
29 31
30 async def on_reaction_add(self, reaction, user):
32 @asyncio.coroutine
33 def on_reaction_add(self, reaction, user):
31 34 if user != self.user: if user != self.user:
32 await self.bot.react_to('on_reaction_add', reaction=reaction,
35 yield from self.bot.react_to('on_reaction_add', reaction=reaction,
33 36 user=user) user=user)
34 37
35 async def on_reaction_remove(self, reaction, user):
38 @asyncio.coroutine
39 def on_reaction_remove(self, reaction, user):
36 40 if user != self.user: if user != self.user:
37 await self.bot.react_to('on_reaction_remove', reaction=reaction,
38 user=user)
41 yield from self.bot.react_to('on_reaction_remove',
42 reaction=reaction, user=user)
39 43
40 async def on_message_edit(self, before, after):
44 @asyncio.coroutine
45 def on_message_edit(self, before, after):
41 46 if before.author != self.user: if before.author != self.user:
42 await self.bot.react_to('on_message_edit', message=before,
47 yield from self.bot.react_to('on_message_edit', message=before,
43 48 after=after) after=after)
44 49
45 async def on_message_delete(self, message):
50 @asyncio.coroutine
51 def on_message_delete(self, message):
46 52 if message.author != self.user: if message.author != self.user:
47 await self.bot.react_to('on_message_delete', message=message)
53 yield from self.bot.react_to('on_message_delete', message=message)
48 54
49 async def on_message(self, message):
55 @asyncio.coroutine
56 def on_message(self, message):
50 57 if message.author != self.user: if message.author != self.user:
51 await self.bot.react_to('on_message', message=message)
58 yield from self.bot.react_to('on_message', message=message)
52 59
53 async def on_member_update(self, before, after):
54 await self.bot.react_to('on_member_update', before=before,
60 @asyncio.coroutine
61 def on_member_update(self, before, after):
62 yield from self.bot.react_to('on_member_update', before=before,
55 63 after=after) after=after)
56 64
57 65 def run(self): def run(self):
File botly/reaction.py changed (mode: 100644) (index 3bcc62a..cf7bdb8)
... ... class ReactionBase:
43 43 """ """
44 44 raise NotImplementedError raise NotImplementedError
45 45
46 async def react(self):
46 @asyncio.coroutine
47 def react(self):
47 48 """Method to be subclassed. Called when conditions were met.""" """Method to be subclassed. Called when conditions were met."""
48 49 raise NotImplementedError raise NotImplementedError
49 50
 
... ... class ReactionBase:
57 58 if self.message: if self.message:
58 59 return self.bot.me.mentioned_in(self.message) return self.bot.me.mentioned_in(self.message)
59 60
60 async def reply(self, message):
61 @asyncio.coroutine
62 def reply(self, message):
61 63 """Coroutine that replies in current chan with given message.""" """Coroutine that replies in current chan with given message."""
62 64 if self.channel: if self.channel:
63 await self.bot.say(self.channel, message)
65 yield from self.bot.say(self.channel, message)
64 66
65 async def send_to_chan(self, channel, message):
67 @asyncio.coroutine
68 def send_to_chan(self, channel, message):
66 69 """Coroutine that send message to given channel.""" """Coroutine that send message to given channel."""
67 await self.bot.say(channel, message)
70 yield from self.bot.say(channel, message)
68 71
69 72 def set_instance_info(self, bot): def set_instance_info(self, bot):
70 73 """Saves botly instance. Only meant to becalled upon module import.""" """Saves botly instance. Only meant to becalled upon module import."""
File botly/task.py changed (mode: 100644) (index b3fc3c8..ca4f4d1)
... ... class TaskBase:
44 44 Only one of these should be called.""" Only one of these should be called."""
45 45 raise NotImplementedError raise NotImplementedError
46 46
47 async def do(self):
47 @asyncio.coroutine
48 def do(self):
48 49 """Proceed with the task's action. To be overwritten when inherited""" """Proceed with the task's action. To be overwritten when inherited"""
49 50 raise NotImplementedError raise NotImplementedError
50 51
 
... ... class TaskBase:
69 70 def print(self, message): def print(self, message):
70 71 self.bot.print('[Tasks][' + self.moduleName + ']' + ' ' + message) self.bot.print('[Tasks][' + self.moduleName + ']' + ' ' + message)
71 72
72 async def announce(self, message):
73 await self.bot.say(self.bot.mainChannel, message)
73 @asyncio.coroutine
74 def announce(self, message):
75 yield from self.bot.say(self.bot.mainChannel, message)
74 76
75 77 def _set_instance_info(self, bot): def _set_instance_info(self, bot):
76 78 """Cache instance metadata""" """Cache instance metadata"""
 
... ... class TaskBase:
92 94 """So name of this task based on the filename will be cached.""" """So name of this task based on the filename will be cached."""
93 95 self.moduleName = name self.moduleName = name
94 96
95 async def _run(self):
97 @asyncio.coroutine
98 def _run(self):
96 99 """Will start the task scheduler. Do not overwrite.""" """Will start the task scheduler. Do not overwrite."""
97 100
98 101 # Wait until the bot is ready before running the task # Wait until the bot is ready before running the task
99 await self.comm.wait_until_ready()
102 yield from self.comm.wait_until_ready()
100 103
101 104 while not self.comm.is_closed or not self.endTask: while not self.comm.is_closed or not self.endTask:
102 105 timeout = self._get_next_timeout() timeout = self._get_next_timeout()
 
... ... class TaskBase:
106 109 if timeout < self.minimumTimeout: if timeout < self.minimumTimeout:
107 110 timeout = self.minimumTimeout timeout = self.minimumTimeout
108 111 # We'll wait till the task is allowed to run # We'll wait till the task is allowed to run
109 await asyncio.sleep(timeout)
112 yield from asyncio.sleep(timeout)
110 113 # Was the communication after waiting for the trigger? # Was the communication after waiting for the trigger?
111 114 if self.comm is None or self.comm.is_closed or self.endTask: if self.comm is None or self.comm.is_closed or self.endTask:
112 115 break break
113 116 # Execute the task # Execute the task
114 await self.do()
117 yield from self.do()
115 118 self.print('Task ended') self.print('Task ended')
116 119
117 120 def _is_day_scheduled(self, day): def _is_day_scheduled(self, day):
File examplebot/reactions/EMPTY.py.example changed (mode: 100644) (index c49ccb6..0d1fb9f)
... ... class Reaction(ReactionBase):
12 12 def prepare_trigger(self, trigger): def prepare_trigger(self, trigger):
13 13 # Prepare trigger here. # Prepare trigger here.
14 14
15 async def react(self):
15 @asyncio.coroutine
16 def react(self):
16 17 # React here. # React here.
17 18
File examplebot/reactions/HELP.py.example changed (mode: 100644) (index 0811430..f25c3a0)
... ... class Reaction(ReactionBase):
50 50 # A trigger can have as many condition as wished, altough abusing # A trigger can have as many condition as wished, altough abusing
51 51 # this will lead to delay for the bot's responses. # this will lead to delay for the bot's responses.
52 52
53 async def react(self):
53 @asyncio.coroutine
54 def react(self):
54 55 ### ###
55 56 # We triggered. Now react accordingly. # We triggered. Now react accordingly.
56 # Remember to use 'await' for Discord API calls
57 # Remember to use 'yield from' for Discord API calls
57 58 # Do not use blocking function calls in this method. # Do not use blocking function calls in this method.
58 59 # #
59 60 ### ###
 
... ... class Reaction(ReactionBase):
81 82 ### ###
82 83 # #
83 84 # Exemple response to a message # Exemple response to a message
84 # await self.reply(self.message.author.mention + ' lol')
85 # yield from self.reply(self.message.author.mention + ' lol')
85 86
File examplebot/reactions/sayhi.py changed (mode: 100644) (index de79e9c..77b064a)
... ... class Reaction(ReactionBase):
16 16 trigger.require_mention(True) trigger.require_mention(True)
17 17 trigger.add_condition('message', '(?i).*((hello)|(hi)|(hey)).*') trigger.add_condition('message', '(?i).*((hello)|(hi)|(hey)).*')
18 18
19 async def react(self):
19 @asyncio.coroutine
20 def react(self):
20 21 affinity = self.knowledge.users.get(self.author.id)['BotAffinity'] affinity = self.knowledge.users.get(self.author.id)['BotAffinity']
21 22 if affinity is None: if affinity is None:
22 23 affinity = 0 affinity = 0
23 24
24 25 if affinity < 0: if affinity < 0:
25 await self.reply(self.author.mention + " I don't like you.")
26 yield from self.reply(self.author.mention + " I don't like you.")
26 27 elif affinity > 0: elif affinity > 0:
27 await self.reply(self.author.mention + " Hi buddy!")
28 yield from self.reply(self.author.mention + " Hi buddy!")
28 29 else: else:
29 await self.reply(self.author.mention + ' Hello.')
30 yield from self.reply(self.author.mention + ' Hello.')
30 31
Hints:
Before first commit, do not forget to setup your git environment:
git config --global user.name "your_name_here"
git config --global user.email "your@email_here"

Clone this repository using HTTP(S):
git clone https://rocketgit.com/user/detche/Botly

Clone this repository using ssh (do not forget to upload a key first):
git clone ssh://rocketgit@ssh.rocketgit.com/user/detche/Botly

Clone this repository using git:
git clone git://git.rocketgit.com/user/detche/Botly

You are allowed to anonymously push to this repository.
This means that your pushed commits will automatically be transformed into a merge request:
... clone the repository ...
... make some changes and some commits ...
git push origin main