command.py 10.4 KB
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @Time    : 2020-02-13 09:25
# @Author  : Lemon
# @File    : command.py
# @Software: PyCharm
import os
import uuid
from base64 import b64decode

from fbchat import ThreadType, EmojiSize, TypingStatus, ImageAttachment, AudioAttachment, FileAttachment, \
    ShareAttachment, VideoAttachment

from lib import common, download
from lib.common import WorkPlace, College


def _send_msg(local_func, remote_func, to, content, thread_type, suffix):
    _type = getattr(ThreadType, thread_type.upper())
    if content.startswith('http'):
        res = remote_func(content, thread_id=to, thread_type=_type)
    else:
        _temp = b64decode(content.encode('utf-8'))
        _temp_path = 'filecache'
        if not os.path.exists(_temp_path): os.mkdir(_temp_path)
        filename = os.path.join(_temp_path, '%s.%s' % (uuid.uuid1().hex, suffix))
        with open(filename, 'wb') as f:
            f.write(_temp)
        try:
            res = local_func(filename, thread_id=to, thread_type=_type)
        except Exception as err:
            os.remove(filename)
            raise err
    return res


def _upload_binary(upload_func, set_func, image, setting):
    farr = download.image(image)
    fbid = upload_func(farr)
    if not setting:
        return {"photo_id": fbid}
    else:
        return set_func(fbid)


class Executor():

    def __init__(self, client):
        self.client = client

    def textMsg(self, to, content, thread_type="USER"):
        _type = getattr(ThreadType, thread_type.upper())
        res = self.client.sendMessage(message=content, thread_id=to, thread_type=_type)
        return res

    def imageMsg(self, to, image, thread_type="USER", suffix='jpg'):
        return _send_msg(self.client.sendLocalImage,
                         self.client.sendRemoteImageSalt,
                         to,
                         image,
                         thread_type,
                         suffix)

    def voiceMsg(self, to, voice, thread_type='USER', suffix='mp3'):
        return _send_msg(self.client.sendLocalVoiceClips,
                         self.client.sendRemoteVoiceClips,
                         to,
                         voice,
                         thread_type,
                         suffix)

    def fileMsg(self, to, link, thread_type="USER"):
        _type = getattr(ThreadType, thread_type.upper())
        return self.client.sendRemoteFiles(link, thread_id=to, thread_type=_type)

    def stickerMsg(self, to, sticker_id, thread_type="USER"):
        _type = getattr(ThreadType, thread_type.upper())
        return self.client.sendSticker(sticker_id, thread_id=to, thread_type=_type)

    def emojiMsg(self, to, emoji, size='small', thread_type="USER"):
        _type = getattr(ThreadType, thread_type.upper())
        _size = getattr(EmojiSize, size.upper())
        return self.client.sendEmoji(emoji=emoji, size=_size, thread_id=to, thread_type=_type)

    def linkMsg(self, to, link, thread_type='USER'):
        _type = getattr(ThreadType, thread_type.upper())
        return self.client.sendPictureLink(link, thread_id=to, thread_type=_type)

    def waveMsg(self, to, first=True, thread_type='USER'):
        _type = getattr(ThreadType, thread_type.upper())
        return self.client.wave(first, thread_id=to, thread_type=_type)

    def pokeMsg(self, to):
        return self.client.sendPoke(fbid=to)

    def searchForUsers(self, name, limit=5):
        users = self.client.searchForUsers(name, limit)
        keys = ['type', 'gender', 'is_friend', 'name', 'photo', 'uid', 'url']
        result = []
        for u in users:
            info = common.todict(u, keys)
            info['type'] = info.get('type').name
            info['gender'] = 'boy' if info['gender'] == 'male_singular' else 'girl'

            result.append(info)
        return result

    def uploadAvatar(self, image, setting=False):
        return _upload_binary(
            self.client.uploudAvatar,
            self.client.setAvatar,
            image,
            setting
        )

    def uploadCover(self, image, setting=False):
        return _upload_binary(
            self.client.uploadCover,
            self.client.setCover,
            image,
            setting
        )

    def pymkFriends(self, filter_ids: list = []):
        result = self.client._pymk_request_out(filter_ids)
        data = {
            'size': len(result),
            'detail': result,
        }
        return data

    def friendRequests(self, next_url=None, require_gender=True):
        result, next_url = self.client._friendRequest(next_url, require_gender=require_gender)
        data = {
            'size': len(result),
            'detail': result,
            'next_url': 'https://www.facebook.com' + next_url if next_url else None
        }
        return data

    def sentRequests(self, next_url, require_gender):
        result, next_url = self.client._outgoingRequest(next_url, require_gender=require_gender)
        data = {
            'size': len(result),
            'detail': result,
            'next_url': 'https://www.facebook.com' + next_url if next_url else None
        }
        return data

    def fetchUserInfo(self, fbid_list):
        if not isinstance(fbid_list, (tuple, list)):
            raise BaseException("fbid_list 参数要求是文本型列表")
        users = self.client.fetchUserInfo(*fbid_list)
        keys = ['type', 'gender', 'is_friend', 'name', 'photo', 'uid', 'url']
        objects = []
        for _, u in users.items():
            info = common.todict(u, include=keys)
            info['type'] = info.get('type').name
            info['gender'] = 'boy' if info['gender'] == 'male_singular' else 'girl'
            objects.append(info)
        return objects

    def addWork(self, work_detail, privacy='EVERYONE'):
        work = WorkPlace.from_dict(work_detail)
        res = self.client.addWorkPlace(work, privacy)
        return res

    def addSchool(self, school_detail, privacy="EVERYONE"):
        school = College.from_dict(school_detail)
        res = self.client.addCollege(school, privacy)
        return res

    def addHighSchool(self, school_detail: dict, privacy="EVERYONE"):
        school = College.from_dict(school_detail)
        res = self.client.addHighSchool(school, privacy)
        return res

    def setTyping(self, thread_id, status, thread_type='USER'):
        status = getattr(TypingStatus, status.upper())
        _type = getattr(ThreadType, thread_type.upper())
        self.client.setTypingStatus(status, thread_id=thread_id, thread_type=_type)
        return {'success': True}

    def fetchThreadMessages(self, thread_id=None, limit=20, before=None):
        messages = self.client.fetchThreadMessages(thread_id, limit, before)
        list_msg = []
        for msg in messages:
            item = {
                'msgId': msg.uid,
                'timestamp': msg.timestamp,
                'self': msg.author == self.client._uid
            }
            if thread_id in msg.read_by:
                item['is_read'] = True
            else:
                item['is_read'] = False

            if msg.text:
                item['message'] = msg.text
                item['type'] = 'text'
            else:
                if msg.sticker:
                    item['message'] = msg.sticker.url
                    item['type'] = 'sticker'
                elif msg.attachments:
                    attachs = []
                    for attach in msg.attachments:
                        if isinstance(attach, ImageAttachment):
                            if attach.large_preview_url:
                                attachs.append(attach.large_preview_url)
                            elif attach.preview_url:
                                attachs.append(attach.preview_url)
                            elif attach.thumbnail_url:
                                attachs.append(attach.thumbnail_url)
                            item['type'] = 'image'
                        elif isinstance(attach, AudioAttachment):
                            attachs.append(attach.url)
                            item['duration'] = attach.duration
                            item['type'] = 'voice'
                        elif isinstance(attach, FileAttachment):
                            attachs.append(attach.url)
                            item['name'] = attach.name
                            item['type'] = 'file'
                        elif isinstance(attach, ShareAttachment):
                            attachs.append(attach.url)
                            item['title'] = attach.title
                            item['description'] = attach.description
                            item['source'] = attach.source
                            item['type'] = 'link'
                        elif isinstance(attach, VideoAttachment):
                            attachs.append(attach.preview_url)
                            item['duration'] = attach.duration
                            if attach.large_image_url:
                                item['preview_url'] = attach.large_image_url
                            elif attach.medium_image_url:
                                item['preview_url'] = attach.medium_image_url
                            elif attach.small_image_url:
                                item['preview_url'] = attach.small_image_url
                            item['type'] = 'video'
                    if len(attachs) == 1:
                        item['message'] = attachs[0]
                    else:
                        item['message'] = attachs
                else:
                    if msg.source.get('__typename') == 'GenericAdminTextMessage':
                        item['message'] = msg.source.get('snippet')
                        item['type'] = 'admintext'
                    elif 'source:instant_games_game_share' in msg.source.get('tags_list', []):
                        try:
                            target = msg.source.get('extensible_attachment').get('story_attachment').get('target')
                            node = target.get('business_items')['nodes'][0]
                            item['message'] = target.get('message')
                            item['image_url'] = node.get('image_url')
                            item['game_name'] = node.get('name')
                        except:
                            pass
                        item['type'] = 'game'
                    else:
                        item['type'] = 'unknown'
            list_msg.append(item)
        return list_msg