Skip to content

Commit

Permalink
release v2.1.0 (#119)
Browse files Browse the repository at this point in the history
* feat: 私聊

* fix: 只有命令行登陆才修改配置文件

* fix: 判断是否从cli登陆

* #68 私信窗口

* feat: #118 python客户端在线状态记录
fix: 修复私聊通道重复建立的问题

* #103 通知系统

* fix: 正则修改
chore: 支持macos

* chore version => 2.1.0
  • Loading branch information
gakkiyomi authored Nov 27, 2024
1 parent 4606b00 commit 42ac0b8
Show file tree
Hide file tree
Showing 19 changed files with 379 additions and 51 deletions.
13 changes: 7 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
![摸鱼派cn.png](https://b3logfile.com/file/2023/05/摸鱼派-cn-owZQT8f.png)
![摸鱼派cn.png](https://b3logfile.com/file/2023/05/摸鱼派-cn-owZQT8f.png)

# fishpi-pyclient

Expand All @@ -10,11 +10,11 @@

[版本列表](https://github.com/gakkiyomi/fishpi-pyclient/releases)

### Windows系统
### Windows 系统

下载后,双击打开

### MacOS系统
### MacOS 系统

下载后,执行如下命令

Expand All @@ -29,7 +29,7 @@
然后需要在偏好设置这里,如下图:
![WechatIMG482.jpg](https://file.fishpi.cn/2023/12/WechatIMG482-3c599a0e.jpg)

### pip安装
### pip 安装

环境: Python3.9 以上

Expand All @@ -55,6 +55,7 @@ python core.py
- 一键切换
- 更多功能请期待
- 💬 聊天模式
- 💬 私聊
- 💬 聊天吹水
- 🌈 自定义字体颜色
- 🤖️ 自动复读
Expand Down Expand Up @@ -85,8 +86,8 @@ python core.py
- 🈲️ 小黑屋功能
- 拒绝接收黑名单在聊天室发送的信息 (红包除外 😂 )
- 将某人从小黑屋中放出
- 🈲️ 关键字屏蔽
- 发红包🧧
- 🈲️ 关键字屏蔽
- 发红包 🧧
- 拼手气红包
- 普通红包
- 专属红包
Expand Down
2 changes: 2 additions & 0 deletions config.ini
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,8 @@ sentences=["晚上好!","早上好!","工作好累!","那些以前说着永
blacklist=[]
;关键字屏蔽(请使用双引号)
kwBlacklist=["你点的歌来了"]
;关键词提醒
kwNotification=[]
;聊天室用户名颜色配置
#black
#grey
Expand Down
4 changes: 3 additions & 1 deletion requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -7,4 +7,6 @@ colorama==0.4.6
termcolor==2.4.0
prettytable==3.9.0
bs4==0.0.1
html2text==2020.1.16
html2text==2020.1.16
plyer==2.1.0
pyobjus==1.2.3
2 changes: 1 addition & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@

# What packages are required for this module to be executed?
REQUIRED = [
'requests', 'websocket-client', 'click', 'schedule', 'objprint', 'colorama', 'termcolor', 'prettytable', 'bs4', 'html2text'
'requests', 'websocket-client', 'click', 'schedule', 'objprint', 'colorama', 'termcolor', 'prettytable', 'bs4', 'html2text', 'plyer', 'pyobjus'
]

# What packages are optional?
Expand Down
28 changes: 23 additions & 5 deletions src/api/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
from src.utils import UA

from .article import ArticleAPI
from .chat import ChatAPI
from .chatroom import ChatRoomAPI
from .config import GLOBAL_CONFIG
from .user import UserAPI
Expand All @@ -20,27 +21,42 @@ def __init__(self, username: str, password: str, api_key: str) -> None:
self.password = password
self.api_key = api_key
self.ws: dict[str, Any] = {}
self.is_online = False
self.in_chatroom = False

def online(self, func) -> None:
def online(self, *funcs) -> None:
if (len(self.api_key) != 0):
API.set_token(self.api_key)
API.set_current_user(self.username)
else:
API.login(self.username, self.password)
self.api_key = API.api_key
func()
self.is_online = True
for func in funcs:
func()
self.in_chatroom = True
GLOBAL_CONFIG.auth_config.username = self.username
GLOBAL_CONFIG.auth_config.password = self.password
GLOBAL_CONFIG.auth_config.key = self.api_key
API.user_key_write_to_config_file()

def out_chatroom(self) -> None:
if 'fishpi.cn/chat-room-channel' in self.ws:
self.ws['fishpi.cn/chat-room-channel'].stop()
self.in_chatroom = False

def offline(self) -> None:
keys = list(self.ws.keys())
for key in keys:
self.ws[key].stop()
self.is_online = False
self.in_chatroom = False

def out_chat(self) -> None:
if 'fishpi.cn/chat-channel' in self.ws:
self.ws['fishpi.cn/chat-channel'].stop()

def chat(self, func) -> None:
self.out_chat()
self.out_chatroom()
func()


class FishPi(Base):
Expand All @@ -49,13 +65,15 @@ def __init__(self):
self.user = UserAPI()
self.chatroom = ChatRoomAPI()
self.article = ArticleAPI()
self.chat = ChatAPI()
super().__init__(self)

def set_token(self, key):
super().set_token(key)
self.user.set_token(key)
self.chatroom.set_token(key)
self.article.set_token(key)
self.chat.set_token(key)

def get_breezemoons(self, page: int = 1, size: int = 10) -> dict | None:
res = requests.get(
Expand Down
51 changes: 51 additions & 0 deletions src/api/chat.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
# -*- coding: utf-8 -*-
import json

import requests

from src.utils import UA

from .base import Base
from .config import GLOBAL_CONFIG


class ChatAPI(Base):

def __init__(self):
pass

def unread(self) -> None | dict:
if self.api_key == '':
return None
resp = requests.get(f"{GLOBAL_CONFIG.host}/chat/has-unread?apiKey={self.api_key}",
headers={'User-Agent': UA})
return json.loads(resp.text)

def get_list(self) -> list[dict]:
if self.api_key == '':
return None
resp = requests.get(f"{GLOBAL_CONFIG.host}/chat/get-list?apiKey={self.api_key}",
headers={'User-Agent': UA})
ret = json.loads(resp.text)
if ret['result'] == 0:
return ret['data']
else:
return []

def render_recent_chat_users(self) -> None:
[print(f"{user['receiverUserName']} {self.__render_online_flag(user['receiverOnlineFlag'])} : {user['preview']}")
for user in self.get_list()]

def __render_online_flag(self, is_online: bool) -> str:
return '[在线]' if is_online else '[离线]'

def get_msg(self, user: str, page: int = 1) -> list[dict]:
if self.api_key == '':
return None
resp = requests.get(f"{GLOBAL_CONFIG.host}/chat/get-message?apiKey={self.api_key}&toUser={user}&page={page}&pageSize=20",
headers={'User-Agent': UA})
ret = json.loads(resp.text)
if ret['result'] == 0:
return ret['data']
else:
return []
4 changes: 3 additions & 1 deletion src/api/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ def to_config(self) -> dict:


class ChatConfig(object):
def __init__(self, blacklist: list[str] = [], kw_blacklist: list[str] = ['你点的歌来了'], repeat_mode_switch=False, frequency=5, soliloquize_switch=False,
def __init__(self, blacklist: list[str] = [], kw_notification: list[str] = [], kw_blacklist: list[str] = ['你点的歌来了'], repeat_mode_switch=False, frequency=5, soliloquize_switch=False,
soliloquize_frequency=20, sentences: list[str] = [], answer_mode: bool = False, fish_ball: str = '凌 捞鱼丸',
chat_user_color: str | None = None, chat_content_color: str | None = None):
self.repeat_mode_switch = repeat_mode_switch
Expand All @@ -67,6 +67,7 @@ def __init__(self, blacklist: list[str] = [], kw_blacklist: list[str] = ['你点
'吃饭了没有?', '💗 爱你哟!'] + sentences
self.blacklist = blacklist
self.kw_blacklist = kw_blacklist
self.kw_notification = kw_notification
self.answer_mode = answer_mode
self.fish_ball = fish_ball
self.chat_user_color = chat_user_color
Expand All @@ -83,6 +84,7 @@ def to_config(self) -> dict:
'sentences': '[' + ",".join('\"'+item+'\"' for item in self.sentences) + ']',
'blacklist': '[' + ",".join('\"'+item+'\"' for item in self.blacklist) + ']',
'kwBlacklist': '[' + ",".join('\"'+item+'\"' for item in self.kw_blacklist) + ']',
'kwNotification': '[' + ",".join('\"'+item+'\"' for item in self.kw_notification) + ']',
'chatUserColor': self.chat_user_color,
'chatContentColor': self.chat_content_color
}
Expand Down
5 changes: 5 additions & 0 deletions src/api/enum.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
# -*- coding: utf-8 -*-
import enum
NTYPE = enum.Enum('Notification_type', [
'FROM_CHATROOM', 'FROM_CHAT', 'FROM_KEYWORD'])
CODE = enum.Enum('REDPACKET_CODE', ['SUCCESS', 'LOSED', 'NOT_ME', "ZERO"])
9 changes: 8 additions & 1 deletion src/api/ws.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import ssl
import threading
from abc import ABC, abstractmethod
from urllib.parse import urlencode

import websocket

Expand Down Expand Up @@ -43,7 +44,13 @@ def stop(self):

def aysnc_start_ws(ws: WS):
websocket.enableTrace(False)
ws_instance = websocket.WebSocketApp(f"wss://{ws.ws_url}?apiKey={API.api_key}",
if hasattr(ws, 'params'):
query_string = urlencode(ws.params)
base_url = f"wss://{ws.ws_url}?apiKey={API.api_key}"
ws_url = f"{base_url}&{query_string}" if query_string else base_url
else:
ws_url = f"wss://{ws.ws_url}?apiKey={API.api_key}"
ws_instance = websocket.WebSocketApp(ws_url,
on_open=ws.on_open,
on_message=ws.on_message,
on_error=ws.on_error,
Expand Down
14 changes: 11 additions & 3 deletions src/core/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,11 @@
RedPacketConfig,
init_defualt_config,
)
from src.utils import HOST
from src.utils import HOST, cli_login

from .chatroom import ChatRoom, init_soliloquize
from .command import init_cli
from .user import User


class Initor(ABC):
Expand Down Expand Up @@ -102,6 +103,8 @@ def exec(self, api: FishPi, options: CliOptions) -> None:
GLOBAL_CONFIG.auth_config.password,
GLOBAL_CONFIG.auth_config.mfa_code)
GLOBAL_CONFIG.auth_config.key = api.api_key
if cli_login(GLOBAL_CONFIG.auth_config.username):
api.user_key_write_to_config_file()
else:
# 直接使用api-key
username = api.user.get_username_by_key(
Expand All @@ -122,13 +125,15 @@ def exec(self, api: FishPi, options: CliOptions) -> None:
GLOBAL_CONFIG.auth_config.password,
GLOBAL_CONFIG.auth_config.mfa_code)
GLOBAL_CONFIG.auth_config.key = api.api_key
if cli_login(GLOBAL_CONFIG.auth_config.username):
api.user_key_write_to_config_file()
if len(GLOBAL_CONFIG.auth_config.accounts) != 0:
api.sockpuppets = {account[0]: UserInfo(
account[0], account[1], '') for account in GLOBAL_CONFIG.auth_config.accounts}
api.sockpuppets[api.current_user] = UserInfo(
api.current_user, GLOBAL_CONFIG.auth_config.password, api.api_key)
api.sockpuppets[api.current_user].is_online = True
api.user_key_write_to_config_file()
api.sockpuppets[api.current_user].in_chatroom = True
User().online(api.sockpuppets[api.current_user])


class ChaRoomInitor(Initor):
Expand Down Expand Up @@ -276,6 +281,9 @@ def init_chat_config(config: ConfigParser) -> ChatConfig:
ret.kw_blacklist = json.loads(config.get('chat', 'kwBlacklist'))
if ret.kw_blacklist.__contains__(''):
ret.kw_blacklist.remove('')
ret.kw_notification = json.loads(config.get('chat', 'kwNotification'))
if ret.kw_notification.__contains__(''):
ret.kw_notification.remove('')
ret.fish_ball = config.get('chat', "fishBall")
init_chat_color(ret, config)
return ret
Expand Down
40 changes: 40 additions & 0 deletions src/core/chat.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
# -*- coding: utf-8 -*-

from src.api import API
from src.api.ws import WS


class Chat(WS):
WS_URL = 'fishpi.cn/chat-channel'

def __init__(self, to: str) -> None:
self.params = {'toUser': to}
super().__init__(Chat.WS_URL, [render])

def on_open(self, ws):
print(f"正在与{self.params['toUser']}私聊!")
[render(API, item)
for item in reversed(API.chat.get_msg(self.params['toUser']))]

def on_error(self, ws, error):
print(f"私聊通道初始化失败, {self.params['toUser']}不存在!")
self.stop()

def on_close(self, ws, close_status_code, close_msg):
print('私聊结束')

def sender(self, msg: str):
self.instance.send(msg)


def render(api, message: dict):
time = message["time"]
sender_name = message["senderUserName"]
if sender_name == api.current_user:
print(f"\t\t\t\t\t\t[{time}]")
print(f'\t\t\t\t\t\t你说: {message["markdown"]}')
else:
print(f"[{time}]")
print(f"{sender_name}说:")
print(message['markdown'])
print("\r\n")
Loading

0 comments on commit 42ac0b8

Please sign in to comment.