Skip to content

Commit 1e023d5

Browse files
committed
204 Create a script for the workshop leader
1 parent 8fff6dd commit 1e023d5

6 files changed

Lines changed: 147 additions & 6 deletions

File tree

puma/apps/android/teleguard/teleguard.py

Lines changed: 54 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,11 @@
1+
from typing import List
2+
3+
from appium.webdriver import WebElement
14
from appium.webdriver.common.appiumby import AppiumBy
25

36
from puma.apps.android.teleguard.xpaths import *
47
from puma.state_graph.action import action
5-
from puma.state_graph.puma_driver import PumaDriver, supported_version
8+
from puma.state_graph.puma_driver import PumaDriver, supported_version, PumaClickException
69
from puma.state_graph.state import ContextualState, SimpleState, compose_clicks
710
from puma.state_graph.state_graph import StateGraph
811

@@ -111,14 +114,61 @@ def add_contact(self, teleguard_id: str):
111114
self.driver.click(CONVERSATION_STATE_INVITE)
112115

113116
@action(conversations_state)
114-
def accept_invite(self):
117+
def invite_received(self, scroll: bool = False, max_swipes: int = 10) -> bool:
118+
"""
119+
Checks whether an invite has been received. By default this method does not scroll to look for an invite.
115120
"""
116-
Accepts an invite from another user.
121+
if scroll:
122+
try:
123+
self.driver.swipe_to_find_element(CONVERSATION_STATE_YOU_HAVE_BEEN_INVITED, max_swipes=max_swipes)
124+
return True
125+
except PumaClickException:
126+
return False
127+
return self.driver.is_present(CONVERSATION_STATE_YOU_HAVE_BEEN_INVITED)
128+
129+
@action(conversations_state)
130+
def accept_invite(self) -> str:
131+
"""
132+
Accepts an invite from another user and returns the name of the accepted invite.
117133
118134
If there are multiple invites, only the topmost invite in the UI will be accepted.
135+
136+
This method returns the name of the user that sent an invite. If no invite was sent, an exception is raised.
119137
"""
120138
self.driver.swipe_to_click_element(CONVERSATION_STATE_YOU_HAVE_BEEN_INVITED)
121-
self.driver.click(CONVERSATION_STATE_ACCEPT_INVITE)
139+
name = self.driver.get_element(CONVERSATION_STATE_INVITATION_NAME).get_attribute('content-desc')
140+
self.driver.click(CONVERSATION_STATE_INVITATION_ACCEPT)
141+
return name
142+
143+
def _extract_name(self, conversation_row: WebElement) -> str:
144+
"""
145+
Given a conversation row, extracts the name of the conversation.
146+
For users with an avatar, the first line of the content description is the conversation name.
147+
For users without an avatar, there is an extra first line with just the first letter of the name.
148+
We try to detect this pattern and return the first or second line based on this.
149+
"""
150+
content_description = conversation_row.get_attribute('content-desc')
151+
lines = content_description.split('\n')[:2]
152+
if len(lines[0])>1:
153+
return lines[0]
154+
elif lines[1][0] == lines[0]:
155+
return lines[1]
156+
else:
157+
return lines[0]
158+
159+
@action(conversations_state)
160+
def conversations_with_unread_messages(self) -> List[str]:
161+
"""
162+
Returns a list of names of conversations that have unread messages.
163+
"""
164+
try:
165+
elements = self.driver.get_elements(CONVERSATION_STATE_UNREAD_MESSAGES)
166+
names = [self._extract_name(e) for e in elements]
167+
return names
168+
except PumaClickException:
169+
return []
170+
171+
122172

123173
@action(chat_state)
124174
def send_message(self, message: str, conversation: str = None):

puma/apps/android/teleguard/xpaths.py

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,13 +7,16 @@
77
CONVERSATION_STATE_EDIT_TEXT = '//android.widget.EditText'
88
CONVERSATION_STATE_INVITE = '//android.widget.Button[@content-desc="INVITE"]'
99
CONVERSATION_STATE_YOU_HAVE_BEEN_INVITED = '//android.view.View[contains(@content-desc, "You have been invited")]'
10-
CONVERSATION_STATE_ACCEPT_INVITE = '//android.widget.Button[@content-desc="ACCEPT INVITE"]'
10+
CONVERSATION_STATE_INVITATION_ID = '//android.view.View[starts-with(lower-case(@content-desc), "teleguard id:")]'
11+
CONVERSATION_STATE_INVITATION_NAME = '//android.view.View[starts-with(lower-case(@content-desc), "teleguard id:")]/preceding-sibling::*[last()]'
12+
CONVERSATION_STATE_INVITATION_ACCEPT = '//android.widget.Button[@content-desc="ACCEPT INVITE"]'
13+
CONVERSATION_STATE_UNREAD_MESSAGES = '//*[@content-desc and matches(@content-desc, "\\n\\d$")]'
1114

1215
CHAT_STATE_CONVERSATION_NAME = ('//android.widget.FrameLayout[@resource-id="android:id/content"]/android.widget.FrameLayout/android.widget.FrameLayout/android.view.View/android.view.View/android.view.View/android.view.View/android.view.View[1]/android.view.View[2]/android.widget.ImageView[2][@content-desc]|'
1316
'//android.widget.FrameLayout[@resource-id="android:id/content"]/android.widget.FrameLayout/android.widget.FrameLayout/android.view.View/android.view.View/android.view.View/android.view.View/android.view.View[1]/android.view.View[2]/android.view.View[1][@content-desc]')
1417
CHAT_STATE_TEXT_FIELD = '//android.widget.EditText[@hint="Send a message"]'
1518
CHAT_STATE_SEND_MEDIA_BUTTON = '//android.widget.FrameLayout[@resource-id="android:id/content"]/android.widget.FrameLayout/android.widget.FrameLayout/android.view.View/android.view.View/android.view.View/android.view.View/android.widget.ImageView[2]'
16-
CHAT_STATE_SEND_BUTTON = '//android.widget.FrameLayout[@resource-id="android:id/content"]/android.widget.FrameLayout/android.widget.FrameLayout/android.view.View/android.view.View/android.view.View/android.view.View/android.widget.ImageView[3]'
19+
CHAT_STATE_SEND_BUTTON = '//android.widget.FrameLayout[@resource-id="android:id/content"]/android.widget.FrameLayout/android.widget.FrameLayout/android.view.View/android.view.View/android.view.View/android.view.View/android.widget.ImageView[last()]'
1720
CHAT_STATE_MICROPHONE_BUTTON = '//android.widget.FrameLayout[@resource-id="android:id/content"]/android.widget.FrameLayout/android.widget.FrameLayout/android.view.View/android.view.View/android.view.View/android.view.View/android.widget.ImageView[4]'
1821
CHAT_STATE_THREE_DOTS = '//android.widget.FrameLayout[@resource-id="android:id/content"]/android.widget.FrameLayout/android.widget.FrameLayout/android.view.View/android.view.View/android.view.View/android.view.View/android.view.View[1]/android.view.View[2]/android.widget.ImageView[last()]'
1922

tutorial/2026/workshop_leader/__init__.py

Whitespace-only changes.
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
Thank you for your message! I've received it loud and clear.
2+
I appreciate your message! Just to let you know, I'm not a chatbot, but I've noted your input.
3+
Message received! Thank you for reaching out. Just a reminder, I'm not capable of continuing the conversation like a person.
4+
Thanks for the note! I understand your message, but please remember that I'm a server, not a chatbot.
5+
Your message has been received! Thanks for sharing. I'm here for processing, not chatting.
6+
Thanks for your input! Just so you know, I'm not a conversational AI, but I acknowledge your message.
7+
Message confirmed! Thank you for sending it. I'm programmed for service, not conversation.
8+
I've received your message. Thank you! Bear in mind, I don't have the capability for back-and-forth chatting.
9+
Thanks! Your message has been noted. I'm here to assist, not to converse like a human.
10+
Message received! Thank you for contacting me. I can only process requests, not engage in dialogue.
11+
Your message has reached me! I appreciate it. However, remember I'm not designed for real conversation.
12+
Thank you! I've registered your message. Please note that I operate as a server, not a chatbot.
13+
Acknowledged! Your message is received. Just a heads-up, I don't engage in conversations.
14+
Thanks for your message! I've received it and will process accordingly. Not a chatbot here!
15+
Confirmation received! I appreciate your input, but I'm not equipped for conversation.
16+
I've got your message! Thanks! Just a reminder that I'm here to serve, not to chat.
17+
Message noted! Thank you for reaching out. I don't have conversational capabilities.
18+
I appreciate your input! Your message is received, but I'm not a conversational AI.
19+
Thank you! Your message has been acknowledged. I can't continue a dialogue like a chatbot.
20+
Message received with thanks! Just so you know, I'm not designed for conversational exchange.
21+
Thanks for your message! It has been logged. I'm more of a server than a conversationalist.
22+
I've successfully received your message! Thank you. I'm not capable of chatting, though.
23+
Acknowledged! Your message is received. Keep in mind I don't engage in back-and-forth.
24+
Thank you for your message! I recognize it, but I'm not a chatbot.
25+
Message received! Thanks! Just a reminder, I'm not programmed for larger conversations.
26+
I've received your note! Thank you for sharing. Remember, I'm a service, not a chatbot.
27+
Thank you! Your message has been noted. I can't follow up like a conversational AI.
28+
I appreciate your message! It's been acknowledged. I'm not capable of having real conversations.
29+
Thanks for your input! Your message was received. I'm not equipped for chat interactions.
30+
Message confirmed! I appreciate you reaching out. However, I'm not a chatbot with dialogue skills.
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
Hello there, thanks for inviting me!
2+
Greetings! It's a pleasure to join the conversation.
3+
Hi! Thanks for the invite; how can I assist you today?
4+
Hello! I'm excited to chat with you.
5+
Hey there! Glad to be here. What's on your mind?
6+
Salutations! I'm ready to engage in some dialogue.
7+
Hi there! Your invitation is warmly accepted!
8+
Hello! I'm thrilled to connect. What would you like to discuss?
9+
Greetings! Thank you for the warm welcome!
10+
Hi! Happy to chat with you. What do you want to talk about?
11+
Hello! Thank you for inviting me; I'm here to help!
12+
Hey! It's great to be here. What's the topic of conversation?
13+
Hi there! Ready to jump into the discussion.
14+
Hello! Thanks for including me. How can I contribute?
15+
Greetings! Looking forward to a fruitful chat.
16+
Hi! Delighted to join you. What's up?
17+
Hello there! Excited to dive into this conversation.
18+
Hey! I appreciate the invitation. Let's chat!
19+
Hi! I'm here, ready to respond. What's on your agenda?
20+
Greetings! It's wonderful to connect. What shall we discuss?
21+
Hello! Thank you for the invite. Let's get started!
22+
Hey there! I'm looking forward to our chat.
23+
Hi! Thank you for involving me in this conversation.
24+
Hello! I'm at your service. What's the first topic?
25+
Greetings! Ready to engage in a lively discussion!
26+
Hi! Glad to be part of this. What's on your mind?
27+
Hello! Excited to hear from you. What can I do for you?
28+
Hey! Thanks for having me; I'm ready for some dialogue.
29+
Hi there! Looking forward to chatting with you.
30+
Greetings! Let's make this chat interesting!
31+
Hello! I appreciate your invitation. Let's discuss!
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
import random
2+
from time import sleep
3+
4+
from puma.apps.android.teleguard.teleguard import TeleGuard
5+
6+
BLACK_PIXEL = ''
7+
8+
if __name__ == '__main__':
9+
teleguard = TeleGuard(BLACK_PIXEL)
10+
11+
with open('hello_messages.txt', 'r') as f:
12+
hello_messages = f.read().splitlines()
13+
with open('chat_responses.txt', 'r') as f:
14+
responses = f.read().splitlines()
15+
16+
while True:
17+
# check for invites
18+
if teleguard.invite_received():
19+
name = teleguard.accept_invite()
20+
teleguard.send_message(random.choice(hello_messages), conversation=name)
21+
# check for unread messages
22+
conversations_with_unread_messages = teleguard.conversations_with_unread_messages()
23+
for conversation in conversations_with_unread_messages:
24+
teleguard.send_message(random.choice(responses), conversation=conversation)
25+
teleguard.go_to_state(teleguard.conversations_state)
26+
print('nothing to do, sleeping...')
27+
sleep(5)

0 commit comments

Comments
 (0)