em… Is me, that “knock the most diaosi of the code, lose the most money” of the silly eagle development son, the story of the end: no sudden wealth, no tender model, no deep sister…

Once again advise you: stay away from speculation and profiteering, maintain physical and mental health! (Of course, there could be a sequel if you learn machine learning stuff later on.)

Okay, so much chatter, but the reason I’m writing this post is because the most common questions that kids ask in my Py trading group are about robots, and they’re basically questions like:

  • 1. Group leader, how did your robot achieve this?
  • 2. Group leader, why is your APK running without any response?
  • 3. Does group owner support automatically adding mobile phone number as friend?
  • . , etc.

At first, I was a problem solver, but patience is one of the easiest things to wear out. And after learning Python, I become more and more lazy, some tedious and repetitive operations, I will try to automate…. Of course, if you’re sending me money or a girl, I’d be happy to do that, too.

Android accessibility and ItChat are both fairly cliche, and I’ve written several articles about them:

  • AccessibilityService black technology to achieve wechat automatically add friends to pull people into a group chat
  • Automatically grab red envelopes, click “like” moments, AccessibilityService free your hands
  • Details of building wechat robot with Itchat (with three practical examples)
  • Piggy’s Python Learning journey — 18.Python Wechat forwarding small Universe Morning News
  • 19.Python wechat automatic friend verification, automatic reply, send group chat links

Those are the things, those are the routines, most of the time, you just need a little “spirituality”!

It’s like a jigsaw puzzle. You only have seven pieces, but you can make a lot of shapes. Be spiritual! This article takes a look at some of the core points of accessibility and ItChat, and then uses a reader’s bot script as an example to teach you how to implement a wave that hopefully will give you some hints to extend your desired functionality.


Open source wechat personal number interface library – Itchat

Itchat library based on wechat web version, out of several years, wechat is slowly narrowing the function of the web page (because of the abuse of wechat robot), a lot of previously used interface slowly can not be used, such as: pull people into the group, add friends, anyway, there is no web page, now can not be used. Lost a few links:

  • Wechat website login: wx2.qq.com/
  • Itchat’s warehouse address: github.com/littlecoder…
  • Itchat official document: itchat. Readthedocs. IO/useful/latest /

What ItChat can do now: Listen for friends, listen for chats (including group chats), and send messages. There are basically three that are commonly used and available. Of course, if you are willing to pay, you do not need to do so much, there are other ways to pay online: micro friend assistant, Wang Ergou robot, and Xposed plug-in, etc. There are free open source libraries available based on other protocols that I haven’t seen yet. If you know, please feel free to let me know in the comments section!

Use bullet points to refine

If you can, I want you to learn as much as possible about manipulating strings with regular expressions (the basics). Regular expression, regular for string matching, extraction is very practical!

1. Listen for and approve friend requests

@itchat.msg_register(itchat.content.FRIENDS)
def deal_with_friend(msg):
    # Automatically input new friends' messages without reloading the address book
    itchat.add_friend(**msg['Text']) 
Copy the code

You can add a friend by using the add_friend function above. However, sometimes we may need to do some filtering so that all the other people can add you, right, such as filtering the content to contain certain words to be verified, or getting information about the person who added you, such as name, verification information, signature, gender, etc. Let’s directly print out the MSG above, which reads as follows:

{'MsgId': '6930655840618917667'.'FromUserName': 'fmessage'.'ToUserName': '@64fc6691440834f2dfba5489d652e5dbae06da4d57d550757403094424f7ec9c'.'MsgType': 37.'Content': '
      
       
      '.'Status': 3.'ImgStatus': 1, 'CreateTime': 1541558757, 'VoiceLength': 0.'PlayLength': 0.'FileName': ' '.'FileSize': ' '.'MediaId': ' '.'Url': ' '.'AppMsgType': 0.'StatusNotifyCode': 0.'StatusNotifyUserName': ' '.'RecommendInfo': {'UserName': '@156957cc475e1113c0a8fa340eae41ac1d92a12a523302a8eb06208616d656b3'.'NickName': 'Robot Pig'.'QQNum': 0.'Province': ' '.'City': ' '.'Content': 'I'm Robot Pig'.'Signature': '(` o ´ v) ♡'.'Alias': ' '.'Scene': 30.'VerifyFlag': 0.'AttrStatus': 50467109, 'Sex': 2.'Ticket': 'v2_4ed4b6a5ac5ccf04c68c7bd64e4b543ba5babde23ce2985d4317bfc4bb62dcdfd78bb701551e1410fe64836f9bd147199de3e4493a031ea2daf5 2187816d9207@stranger'.'OpCode': 2}.'ForwardFlag': 0.'AppInfo': {'AppID': ' '.'Type': 0}.'HasProductId': 0.'Ticket': ' '.'ImgHeight': 0.'ImgWidth': 0.'SubMsgType': 0.'NewMsgId': 6930655840618917667, 'OriContent': ' '.'EncryFileName': ' '.'User': <User: {'UserName': '@156957cc475e1113c0a8fa340eae41ac1d92a12a523302a8eb06208616d656b3'.'MemberList': <ContactList: []>}>, 'Type': 'Friends'.'Text': {'status': 3.'userName': '@156957cc475e1113c0a8fa340eae41ac1d92a12a523302a8eb06208616d656b3'.'verifyContent': ' '.'autoUpdate': {'UserName': '@156957cc475e1113c0a8fa340eae41ac1d92a12a523302a8eb06208616d656b3'.'NickName': 'Robot Pig'.'QQNum': 0.'Province': ' '.'City': ' '.'Content': 'I'm Robot Pig'.'Signature': '(` o ´ v) ♡'.'Alias': ' '.'Scene': 30.'VerifyFlag': 0.'AttrStatus': 50467109, 'Sex': 2.'Ticket': 'v2_4ed4b6a5ac5ccf04c68c7bd64e4b543ba5babde23ce2985d4317bfc4bb62dcdfd78bb701551e1410fe64836f9bd147199de3e4493a031ea2daf5 2187816d9207@stranger'.'OpCode': 2}}}
Copy the code

Json (MSG, MSG, MSG, MSG, MSG, MSG, MSG, MSG, MSG, MSG, MSG, MSG, MSG, MSG, MSG, MSG, MSG, MSG) Itchat. Storage. Messagequeue. Message) a string is a little mess, with PyCharm create a json file, copy and paste the formatting:

Because, like a dictionary, you can get the values you want in the form of keys, such as MSG [‘Content’] :

<msg fromusername="wxid_gvr9a3le939h22" encryptusername="v1_6a48a18b8d6164b69dfdd3949311cd4bc58d96dfe00636d5e9814ff36b8d107164e768ccd9b2fb911ea9b87ccac42978@stranger" fromnickname="Robot Pig" content="I'm Robot Pig."  shortpy="ROBOTPIG" imagestatus="3" scene="30" country="AD" province="" city="" sign="(` o ´ v) ♡" percard="1" sex="2" alias="" weibo="" albumflag="0" albumstyle="0" albumbgimgid="" snsflag="1" snsbgimgid="http://mmsns.qpic.cn/mmsns/icDH6NcE3zNVBleeQZUzzlnhWk16tIfPKyvsmqWIpUwAxHkvricuNCL2RvGPjS3pVq7miaZQoju8TU/0" snsbgobjectid="12478275406675193980" mhash="197adbfd7de1668f30895d20dfb09b67" mfullhash="197adbfd7de1668f30895d20dfb09b67" bigheadimgurl="http://wx.qlogo.cn/mmhead/ver_1/jYcpsrqBVaxDuMbFgPZwH5F3mvcgKMNVrQXlmmbGWx5p9iaFrYALPyia1b7Izn4YCUYDRXz1jnfKw0eUXvEeEH5 NouILblzLDjog40fqOjIjc/0" smallheadimgurl="http://wx.qlogo.cn/mmhead/ver_1/jYcpsrqBVaxDuMbFgPZwH5F3mvcgKMNVrQXlmmbGWx5p9iaFrYALPyia1b7Izn4YCUYDRXz1jnfKw0eUXvEeEH5 NouILblzLDjog40fqOjIjc/96" ticket="v2_4ed4b6a5ac5ccf04c68c7bd64e4b543b5c95f344b73e23e05f71c527683d8693969fcef8a893316431a660ac382032b022ec8af4d8ae5372e680 931064da1ce3@stranger" opcode="2" googlecontact="" qrticket="" chatroomusername="" sourceusername="" sourcenickname=""><brandlist count="0" ver="688441086"></brandlist></msg>
Copy the code

Create a new XML file, copy and paste it and format it:

It contains the information we want, and we use re to extract the desired data:

msg_pattern = re.compile(',re.S)
Copy the code

Then modify a wave of code:

@itchat.msg_register(itchat.content.FRIENDS)
def deal_with_friend(msg):
    result = msg_pattern.search(msg['Content'])
    if result is not None:
        print('Add person to wechat id:', result.group(1))
        print('Add person username', result.group(2))
        print('Verify content', result.group(3))
        print('Add personal signature', result.group(4))
        print('Add person gender', result.group(5))
        print('Add avatar image', result.group(6))
Copy the code

Try adding it and print the following:

Fine. I got all the info you need, so you can do what you want!

2. Monitor chat messages

This is also easy, you can listen for many types of information, as shown in the following table:

Information types explain
itchat.content.TEXT The text content
itchat.content.MAP Position the text
itchat.content.Card Business card
itchat.content.Note Notify the text
itchat.content.Sharing Share name
itchat.content.RECORDING The recording
itchat.PICTURE Picture/expression
itchat.content.VOICE The recording
itchat.content.ATTACHMENT The attachment
itchat.content.VIDEO A short video
itchat.content.FRIENDS Friend Invitation
itchat.content.SYSTEM System information

Multiple information listeners can be registered. The information registered later has a higher priority than the information registered earlier, and the information with parameters is higher than the information without parameters. The core code example is as follows:

@itchat.msg_register(itchat.content.TEXT)
def reply_msg(msg):
    if msg['Content'] == u'hello':
        itchat.send_msg(msg['User'] ['NickName'] + "Hello!, msg['FromUserName'])
Copy the code

With the above listening and through the request to add friends play the same, according to the key to take the value, or the re to extract the data needed. Here are a few commonly used keys:

msg['Content']  Get the content sent by the user. It is recommended to add u to the matching value, which represents Unicode encoding
msg['User'] ['NickName'] The username used to send the message
msg['FromUserName'] # User name to receive messages, this is not a direct user nickname or wechat account!!
Copy the code

3. Send messages

Itchat supports the following types of messages (not voice) :

The function name role
send_msg() Sending text messages
send_file() Send a file
send_video() Send video
send_image() Sending pictures

The core code example is as follows:

user_info = itchat.search_friends(name='A dead flower')
if len(user_info) > 0:
    Get the username
    user_name = user_info[0]['UserName']
    # Send text messages
    itchat.send_msg('Hello pegg! ', user_name)
    # Send pictures
    time.sleep(10)
    itchat.send_image('cat.jpg', user_name)
    # send file
    time.sleep(10)
    itchat.send_file('19_2.py', user_name)
    # Send video
    time.sleep(10)
    itchat.send_video('sport.mp4', user_name)
Copy the code

It is recommended to add delay to prevent the account from being blocked by sending messages too frequently.

4. Get a group chat membership list

The core code example is as follows:

@itchat.msg_register(itchat.content.TEXT, isGroupChat=True)
def reply_msg(msg):
    print("Received a group message:", msg['ActualNickName'], msg['Content'])
Copy the code

The gameplay is the same as before, in addition, you can call ** MSG. IsAt ** to check if someone @ you.

5. Monitor group information

The core code example is as follows:

@itchat.msg_register([NOTE], isGroupChat=True)
def revoke_msg(msg):
    if 'invite' in str(msg['Text') :# Perform related operations
Copy the code

Is to determine whether the prompt message with group words, well, commonly used probably these, the rest of the document to consult.


Android AccessibilityService – AccessibilityService

In fact, it is an automatic dot dot, no technical content, really!! Before we begin our discussion of AccessibilityService, let’s be clear:

What is automation?

Here is my personal understanding:

The repetitive, monotonous, mechanized tasks that should be done by a human are handed over to a program.

For example, xiaozhu uses wechat to recruit people into the group every day. The required operation steps are as follows:

Yes, you pull a person, it takes more than 20 seconds, each pull is mechanical repetition. If there are 30 people in the group every day, you need to spend: 600s, 10 minutes I have enough to open a King of Glory, others on the points, I still pull people??

Use the AccessibilityService to write an automatic dot-dot-dot tool to free me from this.

1. Custom Service inherits AccessibilityService

AccessibilityService () ¶ OnessibilityService () ¶ OnAccessibilityEvent (AccessibilityEvent event).

The **onAccessibilityEvent method is emitted when the interface changes, such as the top Notification, interface updates, content changes, etc. Click on the AccessibilityEvent** class to see a bunch of event types:

I usually just print out the event.toString() and decide for myself:

A code example is as follows:

What is done here is to determine the Event type and the name of the class that triggered the Event when the barrier-related Event was triggered, and then perform the relevant actions: click, scroll, fill in the text, etc.

2. Several methods to obtain nodes

The node can be located through resource-id and text. If possible, it is recommended to use the latter, because generally, the ID will change after APP update. (Therefore, adaptation is required after wechat update, that is, updating this ID.)

1) View the layout hierarchy through UI Automator

Android Studio is not available in the **android-sdk/tools** directory: Android Studio is available in the **android-sdk/tools directory:

After connecting your phone, click on the top:

You can then see the hierarchy diagram of the current page:

It is important to note that resource-id is not necessarily unique!!

GetRootInActiveWindow () : Gets the root node of the active window and returns an AccessibilityNodeInfo class that represents the state of the View and provides the following useful methods:

  • FindAccessibilityNodeInfosByViewId: node element via the view id.
  • FindAccessibilityNodeInfosByText: node element via the string.
  • GetParent: obtains the parent node.
  • GetChild: Obtains the child node.

In addition, to find the node to pay attention to null, can not find the corresponding node directly call other methods will be null pointer exception!! Find the node and then there are the usual actions, click, long press, scroll and type. A code example is as follows:

Click / * * / node. The performAction (AccessibilityNodeInfo. ACTION_CLICK) / * * / Node. The performAction (AccessibilityNodeInfo. ACTION_LONG_CLICK) / * * / scrolling ListNode. PerformAction (AccessibilityNodeInfo. ACTION_SCROLL_FORWARD) / / scroll up ListNode. PerformAction (AccessibilityNodeInfo. ACTION_SCROLL_BACKWARD) / / scroll down the enter text / * * / val the arguments = Bundle () arguments.putCharSequence(AccessibilityNodeInfo.ACTION_ARGUMENT_SET_TEXT_CHARSEQUENCE,"xxx") editNode.performAction(AccessibilityNodeInfo.ACTION_SET_TEXT, / / Public static void sendTextForEditText(Context Context, AccessibilityNodeInfo editNode, String text) {if(editNode ! = null) { ClipboardManager clipboard = (ClipboardManager)context.getSystemService(Context.CLIPBOARD_SERVICE); ClipData clip = ClipData.newPlainText("text", text); clipboard.setPrimaryClip(clip); / / get focus editNode. PerformAction (AccessibilityNodeInfo. ACTION_FOCUS); / / paste content edittext performAction (AccessibilityNodeInfo ACTION_PASTE); }}Copy the code

In addition, there are AccessibilityService’s own unique methods, such as the mock back key, Home button, etc.

PerformGlobalAction (AccessibilityService. GLOBAL_ACTION_BACK) / / back to back PerformGlobalAction (AccessibilityService. GLOBAL_ACTION_HOME) / / Home button PerformGlobalAction (AccessibilityService. GLOBAL_ACTION_NOTIFICATIONS) / / click on the notificationCopy the code

That’s about it. In addition to getting an ID through the UI Automator, there are several other ways to get an ID.

2) Developer assistant

If your phone root, you can install a ** “developer assistant” **, click the current interface analysis, click the node you want to view, as shown in the picture.

3) Through ADB command

Type in order:

adb shell uiautomator dump /mnt/sdcard/window_dump.xml
adb pull /mnt/sdcard/window_dump.xml
Copy the code

The running result is as shown in the figure:

You can then drop the XML file into the AS, format it, fold it down, and then find the corresponding node:

This method is not recommended, unless the node is obvious, such as text, etc., which can kill you if there are too many levels.


3.AccessibilityService Precautions

There are a few things to note when using the AccessibilityService:

First need to manually open barrier-free service!! The program was turned around and nothing happened, probably because the accessibility service was not enabled! Barrier-free services are generally available in: Accessibility -> Barrier-free, (different phones may be different) find your own dot point APK, turn it on, as shown in the picture:

In addition, it is important to note that sometimes the application may be terminated unexpectedly due to an exception. You need to go to barrier-free to shut down the corresponding service and restart it. And one of the most important areas of accessibility:

Native Android APP!! Yes native!! Now many applications are hybrid applications, for H5 pages, barrier-free services are powerless! This is because the control click event is not generated by onClick, but by directly judging the TouchEvent. Android’s accessibility service does not provide an API for sending down, Move, or Up events. The alternative can only use the phone after root to send global click commands to the system.

It usually takes the node, then gets the region of the node, and then executes the relevant command, such as clicking. Examples of common code are as follows:

/* Run the Shell command */ public static voidexecShellCmd(String CMD) {try {// Apply for root privileges. Process = Runtime.getruntime ()."su"); OutputStream = process.getOutputStream(); DataOutputStream dataOutputStream = new DataOutputStream(outputStream); dataOutputStream.writeBytes(cmd); dataOutputStream.flush(); dataOutputStream.close(); outputStream.close(); } catch (Throwable t) { t.printStackTrace(); }} public static void perforGlobalClick(AccessibilityNodeInfo) {Rect Rect = new Rect(); info.getBoundsInScreen(rect); perforGlobalClick(rect.centerX(), rect.centerY()); } public static void perforGlobalClick(int x, int y) {execShellCmd("input tap " + x + ""+ y); } public void perforGlobalSwipe(int x0, int y0, int x1, int y1) {public void perforGlobalSwipe(int x0, int y0, int x1, int y1) {execShellCmd("input swipe " + x0 + "" + y0 + "" + x1 + ""+ y1); } public static void perforGlobalHome(long delay) {execShellCmd("input keyevent "+ KeyEvent.KEYCODE_HOME); } /* Public static void perforGlobalHome(long delay) {execShellCmd("input keyevent " + KeyEvent.KEYCODE_BACK);
}
Copy the code

Ok, about the gameplay of AccessibilityService about these, then teach you to masturbate a semi-automatic wechat robot.


3. Masturbate your own wechat robot

First list my needs:

  • 1. Automatically pass the verification of others adding friends, send the welcome picture and welcome message;
  • 2. Listen to the message sent by the user and respond to the corresponding message
  • Menu: Returns the menu reply word
  • 1: Join the “Python Learning Exchange Group”
  • 2: Join the “Android Learning Exchange Group”
  • 3: Join the Gossip group
  • 4: Added “Butchpicker’s Wonderful Room”
  • 5: Follow the public account “Pat Boy”
  • 6: Xiaozhu’s “Personal blog”
  • 7: Github for pigs
  • 8: “Tip” the pig
  • 9: Xiaozhu’s wechat (no small talk!)
  • Other, default reply black question mark graph.

Okay, here’s the thing. Itchat doesn’t support getting people into groups right now. What do we do? A compromise is to use the Android AccessibilityService to automatically add people to the group. We can collect the user name of the person who sends to the group and send it to the file transfer assistant periodically (say two hours). Then we can copy and paste the user name into the barrierless script we write. Complete the operation of automatic pull people, because people to copy and paste, so only semi-automatic!

Then the second question, data transfer format, if only a group, the simplest, user name concatenation, carriage return as a separator:

Little A little B little CCopy the code

In this case, since I have multiple groups, readers can choose to join the group they want to join. The method of entering a new line or adding a delimiter is a little low and not easy to expand. In this case, I decide to use Json string to store the user name of the person who adds each group, and finally concatenate it into a Json, as shown in the following example:

{
    "Python": []."Python2": [
        "Zhu wei".Hang."Old man with two guns."
    ]
    "Speak": [
        Hang]."Android": [
        "Zhu wei".Hang]."Guy": []}Copy the code

PS: The reason why Python2 is here is because the group is full, so make a judgment call, if the number of people is 495, add the group to the group. So you also need to monitor the changes in the group, new people coming into the group, get the current group, join the two groups. Also, make a judgment call about who’s in the group. If it’s already in the group, don’t add it to the list. Now that the logic is clear, let’s go straight to the code:

# -*- coding:utf-8 -*-
# wechat Small Universe Assistant
import datetime
import re
import time
import random
import json
import itchat
from itchat.content import *
from apscheduler.schedulers.blocking import BlockingScheduler

# Group chat list
member_python_list = []
member_python_list_2 = []
member_android_list = []
member_speak_list = []

# list of group people
group_python_list = []  # Python
group_python_list_2 = []  # Python 2 group
group_android_list = []  # Android
group_speak_list = []  # chatting

Get a list of people in a group chat
nickname_compile = re.compile(r"\, re.S)

Get the re for the group chat name
group_name_compile = re.compile("' NickName ':' (. 40 {1}) ', 'HeadImgUrl:", re.S)

# Add friends through the welcome message
welcome_words = 4, (ᵔᵕᵔ,) linkage, teh, 😘😘😘\n I am a disabled robot Pig, send keywords: "menu" \n Check out more functions of Pig! '

# menu reply words
menu_answer = 4 (ᵔᵕᵔ) clunky ~🎉🎉🎉, \n' \
              'The available keywords are as follows (enter a number, such as 1) : \n' \
              '🐷 1. Join the "Python Learning Community" \n' \
              '🐷 2. Join "Android Learning Exchange Group" \n' \
              '🐷 3. Join the "gossip group" \n' \
              '🐷 4. Follow the public account "bum boy" \n' \
              '🐷 5. Piglet's "personal blog" \n' \
              '🐷 6. "GitHub" \n' \
              '🐷 7. "tip" \n' \
              '🐷 8. Xiaozhu "wechat" (no chatting oh ~) \n' \
              'Note: please do not reply too often, retarded robots can not chat oh! 🐶 '

# add group to unify reply words
add_group_answer = '🚫 🚫 🚫 FBI Warning! 🚫🚫🚫\n(' ω · ´)ゞ wE are very sorry to inform you that \n\n wechat has blocked the crowd interface, your request to add people to the crowd has been received, and we will put you in the crowd as soon as possible. \n\nヾ Blue ≧ ≦) O Please wait! '

# Repeat group reply words
add_repeat_answer = <(' ^´)> <(' ^´)> <(' ^´)> <(' ^´)> 😠 😠 😠 '

# donate reply words
donate_answer = '(˶ ᵔ ᵕ ᵔ ˶) your reward, have more power to pig liver came out of the more Interesting articles, thanks for support ~ 😊 😊 😊'

# Piggy replies
pig_answer = 4, (ᵔᵕᵔ,) No small talk, welcome to the group if you have any questions.

# 404 reply words
no_match_answer = '!!!!!! We are sorry that the keyword you have typed is wrong, please send "menu" to view the supported digital keyword, remember (· ω · ´ sweet)'.

msg_pattern = re.compile(
    ',
    re.S)


# Automatically add friends
@itchat.msg_register(itchat.content.FRIENDS)
def deal_with_friend(msg):
    result = msg_pattern.search(msg['Content'])
    if result is not None:
        print('Add person to wechat id:', result.group(1))
        print('Add person username', result.group(2))
        print('Verify content', result.group(3))
        print('Add personal signature', result.group(4))
        print('Add person gender', result.group(5))
        print('Add avatar image', result.group(6))

    # itchat.add_friend(** MSG ['Text']) # itchat.add_friend(** MSG ['Text']
    # time.sleep(random.randint(1, 3))
    # itchat.send_msg(welcome_words, msg['RecommendInfo']['UserName'])
    # time.sleep(random.randint(1, 3))
    # itchat.send_image('welcome.png', msg['RecommendInfo']['UserName'])


Automatic reply configuration
@itchat.msg_register([TEXT])
def deal_with_msg(msg):
    text = msg['Content']
    if text == u'menu':
        time.sleep(random.randint(1, 3))
        itchat.send(menu_answer, msg['FromUserName'])
    # Join the Python community
    elif text == u'1':
        time.sleep(random.randint(1, 3))
        nickname = msg['User'] ['NickName']
        if nickname not in member_python_list and nickname not in member_python_list_2:
            itchat.send_msg("【" + nickname + ": children \n" + add_group_answer, msg['FromUserName'])
            if nickname is not None:
                # If the number of people exceeds the threshold, pull into the second group
                if len(member_python_list) >= 495:
                    if nickname not in group_python_list_2:
                        group_python_list_2.append(nickname)
                else:
                    if nickname not in group_python_list:
                        group_python_list.append(nickname)
        else:
            itchat.send_msg(add_repeat_answer, msg['FromUserName'])
    # Join the Android community
    elif text == u'2':
        time.sleep(random.randint(1, 3))
        nickname = msg['User'] ['NickName']
        if nickname not in member_android_list:
            itchat.send_msg("【" + nickname + ": children \n" + add_group_answer, msg['FromUserName'])
            if nickname is not None and nickname not in group_android_list:
                group_android_list.append(nickname)
        else:
            itchat.send_msg(add_repeat_answer, msg['FromUserName'])
    # Join a chat group
    elif text == u'3':
        time.sleep(random.randint(1, 3))
        nickname = msg['User'] ['NickName']
        if nickname not in member_speak_list:
            itchat.send_msg("【" + nickname + ": children \n" + add_group_answer, msg['FromUserName'])
            if nickname is not None and nickname not in group_speak_list:
                group_speak_list.append(nickname)
        else:
            itchat.send_msg(add_repeat_answer, msg['FromUserName'])
    # # the public
    elif text == u'4':
        time.sleep(random.randint(1, 3))
        itchat.send_image('gzh.jpg', msg['FromUserName'])
    # Personal blog
    elif text == u'5':
        time.sleep(random.randint(1, 3))
        return Personal home page - the nuggets' coder - pig: https://juejin.cn/user/4142615541321928 '
    # GitHub
    elif text == u'6':
        time.sleep(random.randint(1, 3))
        return 'https://github.com/coder-pig'
    # exceptional
    elif text == u'7':
        time.sleep(random.randint(1, 3))
        itchat.send_image('ds.gif', msg['FromUserName'])
        time.sleep(random.randint(1, 3))
        itchat.send_msg(donate_answer, msg['FromUserName'])
        time.sleep(random.randint(1, 3))
        itchat.send_image('wxpay.png', msg['FromUserName'])
    # Xiaozhu wechat
    elif text == u'8':
        time.sleep(random.randint(1, 3))
        itchat.send_msg(pig_answer, msg['FromUserName'])
        time.sleep(random.randint(1, 3))
        itchat.send_image('scan_code.png', msg['FromUserName'])
    # Other default replies:
    else:
        time.sleep(random.randint(1, 3))
        itchat.send_image('hrwh.png', msg['FromUserName'])
        time.sleep(random.randint(1, 3))
        itchat.send_msg(no_match_answer, msg['FromUserName'])


@itchat.msg_register([NOTE], isGroupChat=True)
def revoke_msg(msg):
    result = group_name_compile.search(str(msg))
    if result is not None:
        group_name = result.group(1)
        if 'invite' in str(msg['Text']):
            results = nickname_compile.findall(str(msg))
            if group_name == 'Piggy Python Learning Exchange Group':
                member_python_list.clear()
                for result in results:
                    member_python_list.append(result)
            elif group_name == 'Xiaozhu Android Learning Exchange Group':
                member_python_list.clear()
                results = nickname_compile.findall(str(msg))
                for result in results:
                    member_android_list.append(result)
            elif group_name == 'Exchange of skills and tricks 🈲':
                member_python_list.clear()
                results = nickname_compile.findall(str(msg))
                for result in results:
                    member_speak_list.append(result)


# Send a group list
def send_friend_group():
    friend_dict = {"Python": []."Android": []."Speak": []."Python2": []}
    for p in group_python_list:
        friend_dict['Python'].append(p)
    for a in group_android_list:
        friend_dict['Android'].append(a)
    for s in group_speak_list:
        friend_dict['Speak'].append(s)
    for p2 in group_python_list_2:
        friend_dict['Python2'].append(p2)
    if len(friend_dict['Python']) > 0 or len(friend_dict['Android']) > 0 or len(friend_dict['Speak']) > 0 or len(
            friend_dict['Python2']) > 0:
        itchat.send_msg(str(json.dumps(friend_dict, ensure_ascii=False, indent=4)), toUserName="filehelper")
        group_python_list.clear()
        group_python_list_2.clear()
        group_android_list.clear()
        group_speak_list.clear()


Enable scheduled tasks after successful login
def after_login():
    sched.add_job(send_friend_group, 'interval', hours=2)
    sched.start()


UserName = UserName; UserName = UserName
def get_member_list():
    python_chat_rooms = itchat.search_chatrooms(name='Piglet Python Learning Exchange 1 group')
    if len(python_chat_rooms) > 0:
        group_username = python_chat_rooms[0]['UserName']
        result = itchat.update_chatroom(group_username, detailedMember=True)
        member_python_list.clear()
        results = nickname_compile.findall(str(result))
        for result in results:
            member_python_list.append(result)
    python_chat_rooms_2 = itchat.search_chatrooms(name='Piglet Python Learning Exchange 2 groups')
    if len(python_chat_rooms_2) > 0:
        group_username = python_chat_rooms_2[0]['UserName']
        result = itchat.update_chatroom(group_username, detailedMember=True)
        member_python_list_2.clear()
        results = nickname_compile.findall(str(result))
        for result in results:
            python_chat_rooms_2.append(result)
    android_chat_rooms = itchat.search_chatrooms(name='Xiaozhu Android Learning Exchange Group')
    if len(android_chat_rooms) > 0:
        group_username = android_chat_rooms[0]['UserName']
        result = itchat.update_chatroom(group_username, detailedMember=True)
        member_android_list.clear()
        results = nickname_compile.findall(str(result))
        for result in results:
            member_android_list.append(result)
    speak_chat_rooms = itchat.search_chatrooms(name='Exchange of skills and tricks 🈲')
    if len(android_chat_rooms) > 0:
        group_username = speak_chat_rooms[0]['UserName']
        result = itchat.update_chatroom(group_username, detailedMember=True)
        member_speak_list.clear()
        results = nickname_compile.findall(str(result))
        for result in results:
            member_speak_list.append(result)


if __name__ == '__main__':
    sched = BlockingScheduler()
    itchat.auto_login(loginCallback=get_member_list, enableCmdQR=1)
    itchat.run(blockThread=False)
    after_login()
Copy the code

After running, you can test our auto reply:

Yes, the automatic reply function is done, followed by the automatic pull with barrier-free service. First, five group names:

Next, write a Bean class to hold Json data.

Next is the barrier-free service class, feel nothing good to talk about, directly on the code:

package com.coderpig.wechathelper import android.accessibilityservice.AccessibilityService import android.app.Notification import android.app.PendingIntent import android.os.Bundle import android.os.Handler import android.util.Log import android.view.accessibility.AccessibilityEvent import Android. View. The org.eclipse.swt.accessibility. AccessibilityNodeInfo import com. Orhanobut.. Hawk hawk / * * * description: * * @author CoderPig on 2018/04/12 13:47. */ Class HelperService:AccessibilityService() {

    private val TAG = "HelperService"
    private val handler = Handler()
    private var curGroup = ""
    private var mMember = Member()

    override fun onInterrupt() {}

    override fun onAccessibilityEvent(event: AccessibilityEvent) {
        val eventType = event.eventType
        val classNameChr = event.className
        val className = classNameChr.toString()
        Log.d(TAG, event.toString())
        when (eventType) {
            AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED -> {
                if (Hawk.get(Constant.ADD_FRIENDS, false)) {
                    when (className) {
                        "com.tencent.mm.ui.LauncherUI" -> openGroup()
                        "com.tencent.mm.ui.contact.ChatroomContactUI" -> searchGroup()
                        "com.tencent.mm.ui.chatting.ChattingUI" -> openGroupSetting()
                        "com.tencent.mm.chatroom.ui.ChatroomInfoUI" -> openSelectContact()
                        "com.tencent.mm.ui.contact.SelectContactUI" -> addMembers()
                    }
                }
                if (className == "com.tencent.mm.ui.widget.a.c") { dialogClick() } } } } //1. Open group chat private FunopenGroup() {
        mMember = Hawk.get<Member>(Constant.MEMBER)
        if(mMember.python_1.size ! = 0 || mMember.android.size ! = 0 || mMember.speak.size ! = 0 || mMember.python_2.size ! = 0 || mMember.guy.size ! = 0) { curGroup = when { mMember.python_1.size > 0 -> Constant.GROUP_NAME_1 mMember.python_2.size > 0 -> Constant.GROUP_NAME_2 mMember.android.size > 0 -> Constant.GROUP_NAME_3 mMember.speak.size > 0 -> Constant.GROUP_NAME_4 mMember.guy.size > 0 -> Constant.GROUP_NAME_5else -> ""
            }
            val nodeInfo = rootInActiveWindow
            if(nodeInfo ! = null) { val tabNodes = nodeInfo.findAccessibilityNodeInfosByViewId("com.tencent.mm:id/cw2")
                for (tabNode in tabNodes) {
                    if (tabNode.text.toString() == "Address book") {
                        tabNode.parent.performAction(AccessibilityNodeInfo.ACTION_CLICK)
                        handler.postDelayed({
                            val newNodeInfo = rootInActiveWindow
                            if(newNodeInfo ! = null) { val tagNodes = newNodeInfo.findAccessibilityNodeInfosByViewId("com.tencent.mm:id/lv")
                                for (tagNode in tagNodes) {
                                    if (tagNode.text.toString() == "Group") {
                                        tagNode.parent.parent.performAction(AccessibilityNodeInfo.ACTION_CLICK)
                                        break}}}}, 500L)}}}}} //2. Search group chat private funsearchGroup() {
        val nodeInfo = rootInActiveWindow
        if(nodeInfo ! = null) { val nodes = nodeInfo.findAccessibilityNodeInfosByViewId("com.tencent.mm:id/m6")
            for (info in nodes) {
                if (info.text.toString() == curGroup) {
                    info.parent.performAction(AccessibilityNodeInfo.ACTION_CLICK)
                    break}}}} //3. Enable group chat Settings private FunopenGroupSetting() {
        when (curGroup) {
            Constant.GROUP_NAME_1 -> {
                if(mMember.python_1.size > 0) {
                    val nodeInfo = rootInActiveWindow
                    if(nodeInfo ! = null) { nodeInfo.findAccessibilityNodeInfosByViewId("com.tencent.mm:id/j1")[0].performAction(AccessibilityNodeInfo.ACTION_CLICK)
                    }
                }
            }
            Constant.GROUP_NAME_2 -> {
                if(mMember.python_2.size > 0) {
                    val nodeInfo = rootInActiveWindow
                    if(nodeInfo ! = null) { nodeInfo.findAccessibilityNodeInfosByViewId("com.tencent.mm:id/j1")[0].performAction(AccessibilityNodeInfo.ACTION_CLICK)
                    }
                }
            }
            Constant.GROUP_NAME_3 -> {
                if(mMember.android.size > 0) {
                    val nodeInfo = rootInActiveWindow
                    if(nodeInfo ! = null) { nodeInfo.findAccessibilityNodeInfosByViewId("com.tencent.mm:id/j1")[0].performAction(AccessibilityNodeInfo.ACTION_CLICK)
                    }
                }
            }
            Constant.GROUP_NAME_4 -> {
                if(mMember.speak.size > 0) {
                    val nodeInfo = rootInActiveWindow
                    if(nodeInfo ! = null) { nodeInfo.findAccessibilityNodeInfosByViewId("com.tencent.mm:id/j1")[0].performAction(AccessibilityNodeInfo.ACTION_CLICK)
                    }
                }
            }
            Constant.GROUP_NAME_5 -> {
                if(mMember.guy.size > 0) {
                    val nodeInfo = rootInActiveWindow
                    if(nodeInfo ! = null) { nodeInfo.findAccessibilityNodeInfosByViewId("com.tencent.mm:id/j1")[0].performAction(AccessibilityNodeInfo.ACTION_CLICK)
                    }
                }
            }
            else-> { performBackClick() } } } //4. After scrolling, click the Add button to open the page of Adding members private FunopenSelectContact() {

        if(curGroup ! ="") {
            var members = arrayListOf<String>()
            when (curGroup) {
                Constant.GROUP_NAME_1 -> members = mMember.python_1
                Constant.GROUP_NAME_2 -> members = mMember.python_2
                Constant.GROUP_NAME_3 -> members = mMember.android
                Constant.GROUP_NAME_4 -> members = mMember.speak
                Constant.GROUP_NAME_5 -> members = mMember.guy
            }
            if (members.size > 0) {
                val nodeInfo = rootInActiveWindow
                if(nodeInfo ! = null) { val numText = nodeInfo.findAccessibilityNodeInfosByViewId("android:id/text1")[0].text.toString()
                    val memberCount = numText.substring(numText.indexOf("(") + 1,numText.indexOf(")")).toInt()
                    val listNode = nodeInfo.findAccessibilityNodeInfosByViewId("android:id/list") [0]if(memberCount > 100) {
                        listNode.performAction(AccessibilityNodeInfo.ACTION_SCROLL_FORWARD)
                        listNode.performAction(AccessibilityNodeInfo.ACTION_SCROLL_FORWARD)
                    }
                    val scrollNodeInfo = rootInActiveWindow
                    if(scrollNodeInfo ! = null) { handler.postDelayed({ val nodes = scrollNodeInfo.findAccessibilityNodeInfosByViewId("com.tencent.mm:id/dnm")
                            for (info in nodes) {
                                if (info.contentDescription.toString() == "Add member") {
                                    info.parent.performAction(AccessibilityNodeInfo.ACTION_CLICK)
                                    break
                                }
                            }
                        }, 1000L)
                    }
                }
            }
        } else{performBackClick()}} //5addMembers() {var members = arrayListOf<String>() And click ok at the top when (curGroup) {constant.group_name_1 -> members = mmember.python_1 constant.group_name_2 -> members = mMember.python_2 Constant.GROUP_NAME_3 -> members = mMember.android Constant.GROUP_NAME_4 -> members = mMember.speak Constant.GROUP_NAME_5 -> members = mMember.guy }if (members.size > 0) {
            for (i in 0 until members.size) {
                handler.postDelayed({
                    val nodeInfo = rootInActiveWindow
                    if(nodeInfo ! = null) { val editNodes = nodeInfo.findAccessibilityNodeInfosByViewId("com.tencent.mm:id/b26")
                        if(editNodes ! = null && editNodes.size > 0) { val editNode = editNodes[0] val arguments = Bundle() arguments.putCharSequence(AccessibilityNodeInfo.ACTION_ARGUMENT_SET_TEXT_CHARSEQUENCE, members[i]) editNode.performAction(AccessibilityNodeInfo.ACTION_SET_TEXT, arguments) } } }, 500L * (i + 1)) handler.postDelayed({ val cbNodes = rootInActiveWindow.findAccessibilityNodeInfosByViewId("com.tencent.mm:id/om")
                    if(cbNodes ! = null) { val cbNode: AccessibilityNodeInfo?if(cbNodes.size > 0) { cbNode = cbNodes[0] cbNode? .parent? . The performAction (AccessibilityNodeInfo. ACTION_CLICK)}} / / when the last time to empty records, and click the confirm button at the topif (i == members.size - 1) {
                        val m = Hawk.get<Member>(Constant.MEMBER)
                        when (curGroup) {
                            Constant.GROUP_NAME_1 -> m.python_1 = arrayListOf()
                            Constant.GROUP_NAME_2 -> m.python_2 = arrayListOf()
                            Constant.GROUP_NAME_3 -> m.android = arrayListOf()
                            Constant.GROUP_NAME_4 -> m.speak = arrayListOf()
                            Constant.GROUP_NAME_5 -> m.guy = arrayListOf()
                        }
                        Hawk.put(Constant.MEMBER, m)
                        curGroup = ""
                        val sureNodes = rootInActiveWindow.findAccessibilityNodeInfosByViewId("com.tencent.mm:id/j0")
                        if(sureNodes ! = null && sureNodes.size > 0) { sureNodes[0].performAction(AccessibilityNodeInfo.ACTION_CLICK) } } }, 800L * (I + 1))}} // The dialog box automatically clicks private fundialogClick() {
        val inviteNode = rootInActiveWindow.findAccessibilityNodeInfosByViewId("com.tencent.mm:id/au_")[0]
        inviteNode.performAction(AccessibilityNodeInfo.ACTION_CLICK)
    }

    private fun performBackClick() {
        handler.postDelayed({ performGlobalAction(AccessibilityService.GLOBAL_ACTION_BACK) }, 1300L)
    }
}
Copy the code

Then copy the data of the group members returned by ItChat, write it, click to open wechat, and then enjoy automatic group addition, as described in the GIF (accelerated…).

Ok, so much for Android barrier-free service X Itchat to build wechat semi-automatic robot, if you haven’t seen it, I really can’t… Barrier-free services can not only be applied to wechat, but also other native apps, such as the most common automatic punch in, automatic check-in, etc. Readers can expand after learning the method

4. Warehouse address

  • ItChatWXHelper: An Itchat-based robot that works with a barrier-free server to pull people in

  • WechatHelper: Use Android AccessibilityService to automatically add friends and pull people into group chat