|
| 1 | +import asyncio |
| 2 | +import re |
| 3 | +import time |
| 4 | +from datetime import datetime |
| 5 | +from typing import List |
| 6 | + |
| 7 | +from apscheduler.schedulers.asyncio import AsyncIOScheduler |
| 8 | + |
| 9 | +from wechaty import Contact, Room, Wechaty, get_logger, Message |
| 10 | + |
| 11 | +welcome = """=============== Powered by Python-Wechaty =============== |
| 12 | +-------- https://github.com/Chatie/python-wechaty -------- |
| 13 | +Hello, |
| 14 | +I'm a Wechaty Botie with the following super powers: |
| 15 | +1. Find a room |
| 16 | +2. Add people to room |
| 17 | +3. Del people from room |
| 18 | +4. Change room topic |
| 19 | +5. Monitor room events |
| 20 | +6. etc... |
| 21 | +If you send a message of magic word 'ding', |
| 22 | +you will get a invitation to join my own room! |
| 23 | +__________________________________________________ |
| 24 | +Hope you like it, and you are very welcome to |
| 25 | +upgrade me for more super powers! |
| 26 | +Please wait... I'm trying to login in...""" |
| 27 | +HELPER_CONTACT_NAME = '黄纯洪' |
| 28 | + |
| 29 | +print(welcome) |
| 30 | +log = get_logger('RoomBot') |
| 31 | + |
| 32 | + |
| 33 | +async def check_room_join(bot, room, invitee_list, inviter): |
| 34 | + try: |
| 35 | + user_self = bot.user_self() |
| 36 | + if inviter.id != user_self.contact_id: |
| 37 | + await room.say('RULE1: Invitation is limited to me, the owner only. ' |
| 38 | + 'Please do not invite people without notify me.' + inviter) |
| 39 | + await room.say('Please contact me: by send "ding" to me, I will re-send you a invitation. ' |
| 40 | + 'Now I will remove you out, sorry.' + ''.join(invitee_list)) |
| 41 | + await room.topic('ding - warn ' + inviter.name()) |
| 42 | + scheduler = AsyncIOScheduler() |
| 43 | + for i in invitee_list: |
| 44 | + scheduler.add_job(room.delete, args=[i], seconds=10) |
| 45 | + scheduler.start() |
| 46 | + else: |
| 47 | + await room.say('Welcome to my room! :)') |
| 48 | + welcomeTopic = ', '.join(map(lambda c: c.name, invitee_list)) |
| 49 | + await room.topic('ding - welcome ' + welcomeTopic) |
| 50 | + except Exception as e: |
| 51 | + log.exception(e) |
| 52 | + |
| 53 | + |
| 54 | +async def manage_ding_room(bot): |
| 55 | + time.sleep(3) |
| 56 | + log.info('Bot' + 'manage_ding_room()') |
| 57 | + try: |
| 58 | + room = await bot.Room.find(topic='ding') |
| 59 | + if not room: |
| 60 | + log.warning('Bot ' + 'there is no room topic ding(yet)') |
| 61 | + return |
| 62 | + log.info('Bot' + 'start monitor "ding" room join/leave/topic event') |
| 63 | + |
| 64 | + def on_join(inviteeList, inviter): |
| 65 | + log.info('room.on(join) id:', room.room_id) |
| 66 | + check_room_join(bot, room, inviteeList, inviter) |
| 67 | + |
| 68 | + def on_leave(leaverList, remover): |
| 69 | + log.info('Bot' + 'Room EVENT: leave - "%s" leave(remover "%s"), bye bye' % (','.join(leaverList), |
| 70 | + remover or 'unknown')) |
| 71 | + |
| 72 | + def on_topic(topic, oldTopic, changer): |
| 73 | + log.info('Bot' + |
| 74 | + 'Room EVENT: topic - changed from "%s" to "%s" by member "%s"' % (oldTopic, topic, changer.name())) |
| 75 | + |
| 76 | + room.on('join', on_join) |
| 77 | + room.on('leave', on_leave) |
| 78 | + room.on('topic', on_topic) |
| 79 | + except Exception as e: |
| 80 | + log.exception(e) |
| 81 | + |
| 82 | + |
| 83 | +async def put_in_room(contact, room): |
| 84 | + log.info('Bot' + 'put_in_room("%s", "%s")' % (contact.name(), await room.topic())) |
| 85 | + try: |
| 86 | + await room.add(contact) |
| 87 | + scheduler = AsyncIOScheduler() |
| 88 | + scheduler.add_job(lambda x: room.say('Welcome ', contact)) |
| 89 | + scheduler.start() |
| 90 | + except Exception as e: |
| 91 | + log.exception(e) |
| 92 | + |
| 93 | + |
| 94 | +async def get_out_room(contact, room): |
| 95 | + log.info('Bot' + 'get_out_room("%s", "%s")' % (contact, room)) |
| 96 | + try: |
| 97 | + await room.say('You said "ding" in my room, I will remove you out.') |
| 98 | + await room.delete(contact) |
| 99 | + except Exception as e: |
| 100 | + log.exception('get_out_room() exception: ', e) |
| 101 | + |
| 102 | + |
| 103 | +def get_helper_contact(bot): |
| 104 | + log.info('Bot' + 'get_helper_contact()') |
| 105 | + return bot.Contact.find(HELPER_CONTACT_NAME) |
| 106 | + |
| 107 | + |
| 108 | +async def create_ding_room(bot, contact): |
| 109 | + log.info('create_ding_room("%s")' % contact) |
| 110 | + try: |
| 111 | + helperContact = await get_helper_contact(bot) |
| 112 | + if not helperContact: |
| 113 | + log.warning('get_helper_contact() found nobody') |
| 114 | + await contact.say("""You don't have a friend called "%s", because create a new room at |
| 115 | + least need 3 contacts, please set [HELPER_CONTACT_NAME] in the code first!""" % HELPER_CONTACT_NAME) |
| 116 | + return |
| 117 | + log.info('get_helper_contact() ok. got: "%s"' % helperContact.name()) |
| 118 | + contactList = [contact, helperContact] |
| 119 | + await contact.say( |
| 120 | + """There isn't ding room. I'm trying to create a room with "{0}" and you""" % helperContact.name()) |
| 121 | + room = await bot.Room.create(contactList, 'ding') |
| 122 | + log.info('create_ding_room() new ding room created: "%s"' % room) |
| 123 | + await room.topic('ding - created') |
| 124 | + await room.say('ding - created') |
| 125 | + return room |
| 126 | + except Exception as e: |
| 127 | + log.exception('get_helper_contact() exception:', e) |
| 128 | + |
| 129 | + |
| 130 | +class MyBot(Wechaty): |
| 131 | + |
| 132 | + # def on_scan(self, status: ScanStatus, qr_code: Optional[str] = None, |
| 133 | + # data: Optional[str] = None): |
| 134 | + # qr_terminal(qr_code, 1) |
| 135 | + # log.info("{0}\n[{1}] Scan QR Code in above url to login: ".format(qr_code, status)) |
| 136 | + |
| 137 | + def on_error(self, payload): |
| 138 | + log.info(str(payload)) |
| 139 | + |
| 140 | + def on_logout(self, contact: Contact): |
| 141 | + log.info('Bot %s logouted' % contact.name) |
| 142 | + |
| 143 | + async def on_login(self, contact: Contact): |
| 144 | + msg = contact.payload.name + ' logined' |
| 145 | + log.info('bot ' + msg) |
| 146 | + await contact.say(msg) |
| 147 | + |
| 148 | + msg = "setting to manage_ding_room() after 3 seconds..." |
| 149 | + log.info('Bot' + msg) |
| 150 | + print(self.user_self()) |
| 151 | + await contact.say(msg) |
| 152 | + await manage_ding_room(self) |
| 153 | + |
| 154 | + async def on_room_join(self, room: Room, invitees: List[Contact], |
| 155 | + inviter: Contact, date: datetime): |
| 156 | + log.info('Bot' + 'EVENT: room-join - Room "%s" got new member "%s", invited by "%s"' % |
| 157 | + (await room.topic(), ','.join(map(lambda c: c.name, invitees)), inviter.name)) |
| 158 | + print('bot room-join room id:', room.room_id) |
| 159 | + topic = await room.topic() |
| 160 | + await room.say('welcome to "{0}"!'.format(topic), [invitees[0].__str__()]) |
| 161 | + |
| 162 | + async def on_room_leave(self, room: Room, leavers: List[Contact], |
| 163 | + remover: Contact, date: datetime): |
| 164 | + log.info('Bot' + 'EVENT: room-leave - Room "%s" lost member "%s"' % |
| 165 | + (await room.topic(), ','.join(map(lambda c: c.name(), leavers)))) |
| 166 | + topic = await room.topic() |
| 167 | + name = leavers[0].name if leavers[0] else 'no contact!' |
| 168 | + await room.say('kick off "{0}" from "{1}"!'.format(name, topic)) |
| 169 | + |
| 170 | + async def on_room_topic(self, room: Room, new_topic: str, old_topic: str, |
| 171 | + changer: Contact, date: datetime): |
| 172 | + try: |
| 173 | + log.info('Bot' + 'EVENT: room-topic - Room "%s" change topic from "%s" to "%s" by member "%s"' % |
| 174 | + (room, old_topic, new_topic, changer)) |
| 175 | + await room.say('room-topic - change topic from "{0}" to "{1}" ' |
| 176 | + 'by member "{2}"'.format(old_topic, new_topic, changer.name)) |
| 177 | + except Exception as e: |
| 178 | + log.exception(e) |
| 179 | + |
| 180 | + async def on_message(self, msg: Message): |
| 181 | + if msg.age() > 3 * 60: |
| 182 | + log.info('Bot' + 'on(message) skip age("%d") > 3 * 60 seconds: "%s"', msg.age(), msg) |
| 183 | + return |
| 184 | + room = msg.room() |
| 185 | + talker = msg.talker() |
| 186 | + text = msg.text() |
| 187 | + if not talker: |
| 188 | + return |
| 189 | + if msg.is_self(): |
| 190 | + return |
| 191 | + if re.search('^ding$', text): |
| 192 | + if room: |
| 193 | + if re.search('^ding', await room.topic()): |
| 194 | + await get_out_room(talker, room) |
| 195 | + else: |
| 196 | + try: |
| 197 | + dingRoom = await self.Room.find('^ding') |
| 198 | + if dingRoom: |
| 199 | + log.info('Bot' + 'onMessage: got dingRoom: "%s"' % await dingRoom.topic()) |
| 200 | + if await dingRoom.has(talker): |
| 201 | + topic = await dingRoom.topic() |
| 202 | + log.info('Bot' + 'onMessage: sender has already in dingRoom') |
| 203 | + await dingRoom.say('I found you have joined in room "{0}"!'.format(topic), talker) |
| 204 | + await talker.say( |
| 205 | + 'no need to ding again, because you are already in room: "{}"'.format(topic)) |
| 206 | + else: |
| 207 | + log.info('Bot' + 'onMessage: add sender("%s") to dingRoom("%s")' % ( |
| 208 | + talker.name, dingRoom.topic())) |
| 209 | + await talker.say('ok, I will put you in ding room!') |
| 210 | + await put_in_room(talker, dingRoom) |
| 211 | + else: |
| 212 | + log.info('Bot' + 'onMessage: dingRoom not found, try to create one') |
| 213 | + newRoom = await create_ding_room(self, talker) |
| 214 | + print('create_ding_room id:', newRoom.id) |
| 215 | + await manage_ding_room(self) |
| 216 | + except Exception as e: |
| 217 | + log.exception(e) |
| 218 | + |
| 219 | + |
| 220 | +async def main(): |
| 221 | + bot = MyBot() |
| 222 | + await bot.start() |
| 223 | + |
| 224 | + |
| 225 | +if __name__ == '__main__': |
| 226 | + asyncio.run(main()) |
0 commit comments