Skip to content

Commit 8d0c9a9

Browse files
committed
Merge pull request #23 from wardellchandler/nightly
Readme updates for new docstring changes for commands.
2 parents 3f125a1 + bc21ead commit 8d0c9a9

File tree

3 files changed

+106
-111
lines changed

3 files changed

+106
-111
lines changed

Core/Bot.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@
2525
[["bot", "robot", "Yo"], "/think {}"]
2626
],
2727
"development_mode": false,
28-
"commands_admin": ["hangouts", "reload", "quit", "restart", "config", "restart", "block"],
28+
"commands_admin": ["hangouts", "reload", "quit", "config", "block"],
2929
"commands_conversation_admin": ["leave", "echo", "block"]
3030
"commands_enabled": true,
3131
"forwarding_enabled": false,

Core/Commands/ExtraCommands.py

Lines changed: 86 additions & 96 deletions
Original file line numberDiff line numberDiff line change
@@ -82,106 +82,96 @@ def udefine(bot, event, *args):
8282
@DispatcherSingleton.register
8383
def remind(bot, event, *args):
8484
# TODO Implement a private chat feature. Have reminders save across reboots?
85-
if ''.join(args) == '?':
86-
segments = [hangups.ChatMessageSegment('Remind', is_bold=True),
87-
hangups.ChatMessageSegment('\n', hangups.SegmentType.LINE_BREAK),
88-
hangups.ChatMessageSegment(
89-
'Usage: /remind <optional: date [defaults to today]> <optional: time [defaults to an hour from now]> Message'),
90-
hangups.ChatMessageSegment('\n', hangups.SegmentType.LINE_BREAK),
91-
hangups.ChatMessageSegment(
92-
'Usage: /remind'),
93-
hangups.ChatMessageSegment('\n', hangups.SegmentType.LINE_BREAK),
94-
hangups.ChatMessageSegment(
95-
'Usage: /remind delete <index to delete>'),
96-
hangups.ChatMessageSegment('\n', hangups.SegmentType.LINE_BREAK),
85+
"""
86+
*Remind:*
87+
Usage: /remind <optional: date [defaults to today]> <optional: time [defaults to an hour from now]> <message> {/remind 1/1/15 2:00PM Call mom}
88+
Usage: /remind
89+
Usage /remind delete <index to delete> {/remind delete 1}
90+
Purpose: Will post a message on the date and time specified to the current chat. With no arguments, it'll list all the reminders."""
91+
if len(args) == 0:
92+
segments = [hangups.ChatMessageSegment('Reminders:', is_bold=True),
93+
hangups.ChatMessageSegment('\n', hangups.SegmentType.LINE_BREAK)]
94+
if len(reminders) > 0:
95+
for x in range(0, len(reminders)):
96+
reminder = reminders[x]
97+
reminder_timer = reminder[0]
98+
reminder_text = reminder[1]
99+
date_to_post = datetime.now() + timedelta(seconds=reminder_timer.interval)
100+
segments.append(
97101
hangups.ChatMessageSegment(
98-
'Purpose: Will post a message the date and time specified to the current chat. With no arguments, it\'ll list all the reminders.')]
99-
bot.send_message_segments(event.conv, segments)
100-
else:
101-
if len(args) == 0:
102-
segments = [hangups.ChatMessageSegment('Reminders:', is_bold=True),
103-
hangups.ChatMessageSegment('\n', hangups.SegmentType.LINE_BREAK)]
104-
if len(reminders) > 0:
105-
for x in range(0, len(reminders)):
106-
reminder = reminders[x]
107-
reminder_timer = reminder[0]
108-
reminder_text = reminder[1]
109-
date_to_post = datetime.now() + timedelta(seconds=reminder_timer.interval)
110-
segments.append(
111-
hangups.ChatMessageSegment(
112-
str(x + 1) + ' - ' + date_to_post.strftime('%m/%d/%y %I:%M%p') + ' : ' + reminder_text))
113-
segments.append(hangups.ChatMessageSegment('\n', hangups.SegmentType.LINE_BREAK))
114-
segments.pop()
115-
bot.send_message_segments(event.conv, segments)
116-
else:
117-
bot.send_message(event.conv, "No reminders are currently set.")
118-
return
119-
if args[0] == 'delete':
120-
try:
121-
x = int(args[1])
122-
x -= 1
123-
except ValueError:
124-
bot.send_message(event.conv, 'Invalid integer: ' + args[1])
125-
return
126-
if x in range(0, len(reminders)):
127-
reminder_to_remove_text = reminders[x][1]
128-
reminders[x][0].cancel()
129-
reminders.remove(reminders[x])
130-
bot.send_message(event.conv, 'Removed reminder: ' + reminder_to_remove_text)
131-
else:
132-
bot.send_message(event.conv, 'Invalid integer: ' + str(x + 1))
133-
return
134-
135-
def send_reminder(bot, conv, reminder_time, reminder_text, loop):
136-
asyncio.set_event_loop(loop)
137-
bot.send_message(conv, reminder_text)
138-
for reminder in reminders:
139-
if reminder[0].interval == reminder_time and reminder[1] == reminder_text:
140-
reminders.remove(reminder)
141-
142-
args = list(args)
143-
date = str(datetime.now().today().date())
144-
time = str((datetime.now() + timedelta(hours=1)).time())
145-
set_date = False
146-
set_time = False
147-
index = 0
148-
while index < len(args):
149-
item = args[index]
150-
if item[0].isnumeric():
151-
if '/' in item or '-' in item:
152-
date = item
153-
args.remove(date)
154-
set_date = True
155-
index -= 1
156-
else:
157-
time = item
158-
args.remove(time)
159-
set_time = True
160-
index -= 1
161-
if set_date and set_time:
162-
break
163-
index += 1
164-
165-
reminder_time = date + ' ' + time
166-
if len(args) > 0:
167-
reminder_text = ' '.join(args)
102+
str(x + 1) + ' - ' + date_to_post.strftime('%m/%d/%y %I:%M%p') + ' : ' + reminder_text))
103+
segments.append(hangups.ChatMessageSegment('\n', hangups.SegmentType.LINE_BREAK))
104+
segments.pop()
105+
bot.send_message_segments(event.conv, segments)
168106
else:
169-
bot.send_message(event.conv, 'No reminder text set.')
170-
return
171-
current_time = datetime.now()
107+
bot.send_message(event.conv, "No reminders are currently set.")
108+
return
109+
if args[0] == 'delete':
172110
try:
173-
reminder_time = parser.parse(reminder_time)
174-
except (ValueError, TypeError):
175-
bot.send_message(event.conv, "Couldn't parse " + reminder_time + " as a valid date.")
111+
x = int(args[1])
112+
x -= 1
113+
except ValueError:
114+
bot.send_message(event.conv, 'Invalid integer: ' + args[1])
176115
return
177-
if reminder_time < current_time:
178-
reminder_time = current_time + timedelta(hours=1)
179-
reminder_interval = (reminder_time - current_time).seconds
180-
reminder_timer = threading.Timer(reminder_interval, send_reminder,
181-
[bot, event.conv, reminder_interval, reminder_text, asyncio.get_event_loop()])
182-
reminders.append((reminder_timer, reminder_text))
183-
reminder_timer.start()
184-
bot.send_message(event.conv, "Reminder set for " + reminder_time.strftime('%B %d, %Y %I:%M%p'))
116+
if x in range(0, len(reminders)):
117+
reminder_to_remove_text = reminders[x][1]
118+
reminders[x][0].cancel()
119+
reminders.remove(reminders[x])
120+
bot.send_message(event.conv, 'Removed reminder: ' + reminder_to_remove_text)
121+
else:
122+
bot.send_message(event.conv, 'Invalid integer: ' + str(x + 1))
123+
return
124+
125+
def send_reminder(bot, conv, reminder_time, reminder_text, loop):
126+
asyncio.set_event_loop(loop)
127+
bot.send_message(conv, reminder_text)
128+
for reminder in reminders:
129+
if reminder[0].interval == reminder_time and reminder[1] == reminder_text:
130+
reminders.remove(reminder)
131+
132+
args = list(args)
133+
date = str(datetime.now().today().date())
134+
time = str((datetime.now() + timedelta(hours=1)).time())
135+
set_date = False
136+
set_time = False
137+
index = 0
138+
while index < len(args):
139+
item = args[index]
140+
if item[0].isnumeric():
141+
if '/' in item or '-' in item:
142+
date = item
143+
args.remove(date)
144+
set_date = True
145+
index -= 1
146+
else:
147+
time = item
148+
args.remove(time)
149+
set_time = True
150+
index -= 1
151+
if set_date and set_time:
152+
break
153+
index += 1
154+
155+
reminder_time = date + ' ' + time
156+
if len(args) > 0:
157+
reminder_text = ' '.join(args)
158+
else:
159+
bot.send_message(event.conv, 'No reminder text set.')
160+
return
161+
current_time = datetime.now()
162+
try:
163+
reminder_time = parser.parse(reminder_time)
164+
except (ValueError, TypeError):
165+
bot.send_message(event.conv, "Couldn't parse " + reminder_time + " as a valid date.")
166+
return
167+
if reminder_time < current_time:
168+
reminder_time = current_time + timedelta(hours=1)
169+
reminder_interval = (reminder_time - current_time).seconds
170+
reminder_timer = threading.Timer(reminder_interval, send_reminder,
171+
[bot, event.conv, reminder_interval, reminder_text, asyncio.get_event_loop()])
172+
reminders.append((reminder_timer, reminder_text))
173+
reminder_timer.start()
174+
bot.send_message(event.conv, "Reminder set for " + reminder_time.strftime('%B %d, %Y %I:%M%p'))
185175

186176

187177
@DispatcherSingleton.register

readme.md

Lines changed: 19 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ HangoutsBot
44
Setup
55
--------------
66

7-
In order to use this, you'll need to setup a GMail account for logging in, and a config.json file to give the bot its settings. The config file should look like:
7+
In order to use this, you'll need to setup a GMail account for logging in, and a config.json file (placed either at the folder root or in the Core folder) to give the bot its settings. The config file should look something like:
88

99
```JSON
1010
{
@@ -14,7 +14,7 @@ In order to use this, you'll need to setup a GMail account for logging in, and a
1414
[["bot", "robot", "Yo"], "/think {}"]
1515
],
1616
"development_mode": false,
17-
"commands_admin": ["hangouts", "reload", "quit", "restart", "config", "restart", "block"],
17+
"commands_admin": ["hangouts", "reload", "quit", "config", "block"],
1818
"commands_conversation_admin": ["leave", "echo", "block"],
1919
"commands_enabled": true,
2020
"forwarding_enabled": false,
@@ -32,7 +32,9 @@ In order to use this, you'll need to setup a GMail account for logging in, and a
3232
}
3333
}
3434
}
35-
```
35+
```
36+
37+
If you neglect to create a config.json file, this exact one will be created for you in the Core folder.
3638

3739
Line by Line breakdown (excluding braces/brackets):
3840

@@ -54,6 +56,8 @@ Line by Line breakdown (excluding braces/brackets):
5456
16. Start of the "forward_to" array. All conversation IDs listed here will have this conversation forwarded to them.
5557
17. "CONV-ID-HERE" should be replaced with an actual id, which looks something like "Ugxxxxxxxxxxx_xxxxxxxxxxxxx", and then commands will be forwarded to that conversation.
5658

59+
Note: Every top-level argument can be made a conversation level argument, which will overwrite the top level argument for that conversation. For instance, if you put a commands_admin array containing only "quit" and "block" in "CONV-ID-HERE", in the CONV-ID-HERE conversation, all users would be able to run /hangouts, /reload, /config, etc but would still be blocked from running /quit and /block. Conversely, if you put an empty commands_admin array in CONV-ID-HERE, all users in that conversation would be able to run all commands (except any commands in the "commands_conversation_admin" array unless they're a conversation admin.)
60+
5761
A cookies.txt file will also be created, holding the cookies that are valid for your login.
5862

5963
Usage
@@ -72,19 +76,20 @@ Any function created in the ExtraCommands.py file (or any .py file that imports
7276

7377
```python
7478
@DispatcherSingleton.register
75-
def function_for_bot(bot, event, *args):
76-
if ''.join(args) == '?':
77-
segments = [hangups.ChatMessageSegment('New Function For Bot', is_bold=True),
78-
hangups.ChatMessageSegment('\n', hangups.SegmentType.LINE_BREAK),
79-
hangups.ChatMessageSegment('Usage: /function_for_bot <required argument> <optional: optional argument>'),
80-
hangups.ChatMessageSegment('\n', hangups.SegmentType.LINE_BREAK),
81-
hangups.ChatMessageSegment('Purpose: Does a thing.')]
82-
bot.send_message_segments(event.conv, segments)
83-
else:
84-
# Do actual functionality here.
79+
def command(bot, event, *args):
80+
"""Command
81+
Usage: /command <required argument> <optional: optional argument> {for complicated commands, put an example call in curly braces}
82+
Purpose: Does a thing."""
83+
84+
# Do actual functionality here.
8585
```
8686

87-
It should be frowned upon to force a user to put underscores in to use a command, but that's up to you to decide.
87+
The docstring isn't necessary, but should be used as it will be printed out if a user uses "/help \<command name\>" or does "/\<command_name\> ?". Admin-only commands generally don't have help text by default, but that's left up to your discretion.
88+
89+
The bot variable is a reference to the HangoutsBot that is currently running. The event variable is a ConversationEvent that has information about the event (as in, text, the user who sent it, the conversation, and all users in the conversation.) The \*args variable is a tuple of all of the text sent along with the command call, split by whitespace so that you can easily check its values. Look at the DefaultCommands.py file for actual examples of how commands work.
90+
91+
It should be frowned upon to force a user to put underscores in to use a command, but that's up to you to decide.
92+
8893

8994

9095
Have fun botting!

0 commit comments

Comments
 (0)