More codes

- TCP response model
This commit is contained in:
Linloir 2022-10-11 16:02:41 +08:00
parent 239beb43b6
commit f53debfd14
9 changed files with 465 additions and 127 deletions

View File

@ -0,0 +1,12 @@
/*
* @Author : Linloir
* @Date : 2022-10-11 15:18:49
* @LastEditTime : 2022-10-11 15:22:13
* @Description :
*/
abstract class JSONEncodable {
const JSONEncodable();
Map<String, Object?> get jsonObject;
}

View File

@ -0,0 +1,90 @@
/*
* @Author : Linloir
* @Date : 2022-10-11 10:30:05
* @LastEditTime : 2022-10-11 15:36:23
* @Description :
*/
import 'dart:convert';
import 'package:crypto/crypto.dart';
import 'package:flutter/foundation.dart';
import 'package:tcp_client/repositories/common_models/json_encodable.dart';
import 'package:tcp_client/repositories/file_repository/models/local_file.dart';
enum MessageType {
plaintext('plaintext'),
file('file'),
image('image');
factory MessageType.fromStringLiteral(String value) {
return MessageType.values.firstWhere((element) => element._value == value);
}
const MessageType(String value): _value = value;
final String _value;
String get literal => _value;
}
class Message extends JSONEncodable {
final int _userid;
final int _targetid;
final MessageType _contenttype;
final String _content;
final int _timestamp;
late final String _contentmd5;
final LocalFile? _payload;
Message({
required int userid,
required int targetid,
required MessageType contenttype,
required String content,
LocalFile? payload,
required int token
}):
_userid = userid,
_targetid = targetid,
_contenttype = contenttype,
_content = base64.encode(utf8.encode(content)),
_timestamp = DateTime.now().millisecondsSinceEpoch,
_payload = payload {
_contentmd5 = md5.convert(
utf8.encode(content)
..addAll(Uint8List(4)..buffer.asInt32List()[0] = userid)
..addAll(Uint8List(4)..buffer.asInt32List()[0] = targetid)
..addAll(Uint8List(4)..buffer.asInt32List()[0] = _timestamp)
).toString();
}
Message.fromJSONObject({
required Map<String, Object?> jsonObject,
LocalFile? payload
}):
_userid = jsonObject['userid'] as int,
_targetid = jsonObject['targetid'] as int,
_contenttype = MessageType.fromStringLiteral(jsonObject['contenttype'] as String),
_content = jsonObject['content'] as String,
_timestamp = jsonObject['timestamp'] as int,
_contentmd5 = jsonObject['md5encoded'] as String,
_payload = payload;
int get senderID => _userid;
int get recieverID => _targetid;
MessageType get type => _contenttype;
String get contentDecoded => utf8.decode(base64.decode(_content));
String get contentEncoded => _content;
String get contentmd5 => _contentmd5;
int get timeStamp => _timestamp;
LocalFile? get payload => _payload;
@override
Map<String, Object?> get jsonObject => {
'userid': _userid,
'targetid': _targetid,
'contenttype': _contenttype.literal,
'content': _content,
'timestamp': _timestamp,
'md5Encoded': _contentmd5,
'filemd5': payload?.filemd5
};
}

View File

@ -1,19 +0,0 @@
/*
* @Author : Linloir
* @Date : 2022-10-11 10:30:05
* @LastEditTime : 2022-10-11 10:30:12
* @Description :
*/
enum MessageType {
plaintext('plaintext'),
file('file'),
image('image');
factory MessageType.fromStringLiteral(String value) {
return MessageType.values.firstWhere((element) => element._value == value);
}
const MessageType(String value): _value = value;
final String _value;
String get literal => _value;
}

View File

@ -0,0 +1,44 @@
/*
* @Author : Linloir
* @Date : 2022-10-11 15:06:42
* @LastEditTime : 2022-10-11 15:39:38
* @Description :
*/
import 'dart:convert';
import 'package:crypto/crypto.dart';
import 'package:tcp_client/repositories/common_models/json_encodable.dart';
class UserIdentity extends JSONEncodable {
final String _username;
final String _oldPasswd;
final String? _newPasswd;
UserIdentity({
required String username,
required String password,
String? newPassword
}):
_username = base64.encode(utf8.encode(username)),
_oldPasswd = md5.convert(password.codeUnits).toString(),
_newPasswd = newPassword != null ?
md5.convert(newPassword.codeUnits).toString() : null;
UserIdentity.fromJSONObject({
required Map<String, Object?> jsonObject
}):
_username = jsonObject['username'] as String,
_oldPasswd = jsonObject['passwd'] as String,
_newPasswd = jsonObject['newPasswd'] as String?;
String get userName => utf8.decode(base64.decode(_username));
String get password => _oldPasswd;
String? get newPassword => _newPasswd;
@override
Map<String, Object?> get jsonObject => {
'username': _username,
'passwd': _oldPasswd,
'newPasswd': _newPasswd
};
}

View File

@ -0,0 +1,41 @@
/*
* @Author : Linloir
* @Date : 2022-10-11 14:30:10
* @LastEditTime : 2022-10-11 15:39:13
* @Description :
*/
import 'package:tcp_client/repositories/common_models/json_encodable.dart';
class UserInfo extends JSONEncodable {
final int _userid;
final String _username;
final String? _avatar;
const UserInfo({
required int userid,
required String username,
String? avatar
}):
_userid = userid,
_username = username,
_avatar = avatar;
UserInfo.fromJSONObject({
required Map<String, Object?> jsonObject
}):
_userid = jsonObject['userid'] as int,
_username = jsonObject['username'] as String,
_avatar = jsonObject['avatar'] as String?;
int get userID => _userid;
String get userName => _username;
String? get avatarEncoded => _avatar;
@override
Map<String, Object?> get jsonObject => {
'userid': _userid,
'username': _username,
'avatar': _avatar
};
}

View File

@ -1,6 +0,0 @@
/*
* @Author : Linloir
* @Date : 2022-10-11 11:02:19
* @LastEditTime : 2022-10-11 11:02:19
* @Description :
*/

View File

@ -1,16 +1,16 @@
/*
* @Author : Linloir
* @Date : 2022-10-11 09:44:03
* @LastEditTime : 2022-10-11 11:37:13
* @LastEditTime : 2022-10-11 16:01:54
* @Description : Abstract TCP request class
*/
export 'package:tcp_client/repositories/online_service_repository/models/tcp_request.dart';
export 'package:tcp_client/repositories/tcp_repository/models/tcp_request.dart';
import 'dart:convert';
import 'package:crypto/crypto.dart';
import 'package:flutter/foundation.dart';
import 'package:tcp_client/repositories/common_models/message_type.dart';
import 'package:tcp_client/repositories/common_models/message.dart';
import 'package:tcp_client/repositories/common_models/useridentity.dart';
import 'package:tcp_client/repositories/common_models/userinfo.dart';
import 'package:tcp_client/repositories/file_repository/models/local_file.dart';
enum TCPRequestType {
@ -68,43 +68,27 @@ class CheckStateRequest extends TCPRequest {
}
class RegisterRequest extends TCPRequest {
final String _username;
final String _password;
final UserIdentity _identity;
RegisterRequest({
required username,
required password,
required UserIdentity identity,
required token
}):
_username = username,
_password = md5.convert(password.codeUnits).toString(),
super(type: TCPRequestType.register, token: token);
}): _identity = identity, super(type: TCPRequestType.register, token: token);
@override
Map<String, Object?> get body => {
'username': _username,
'passwd': _password
};
Map<String, Object?> get body => _identity.jsonObject;
}
class LoginRequest extends TCPRequest {
final String _username;
final String _password;
LoginRequest({
required String username,
required String password,
required int token
}):
_username = username,
_password = md5.convert(password.codeUnits).toString(),
super(type: TCPRequestType.login, token: token);
final UserIdentity _identity;
LoginRequest({
required UserIdentity identity,
required token
}): _identity = identity, super(type: TCPRequestType.login, token: token);
@override
Map<String, Object?> get body => {
'username': _username,
'passwd': _password
};
Map<String, Object?> get body => _identity.jsonObject;
}
class LogoutRequest extends TCPRequest {
@ -122,97 +106,43 @@ class GetProfileRequest extends TCPRequest {
}
class ModifyPasswordRequest extends TCPRequest {
final String _username;
final String _oldPassword;
final String _newPassword;
final UserIdentity _identity;
ModifyPasswordRequest({
required String username,
required String oldPassword,
required String newPassowrd,
required int token
}):
_username = username,
_oldPassword = md5.convert(oldPassword.codeUnits).toString(),
_newPassword = md5.convert(newPassowrd.codeUnits).toString(),
super(type: TCPRequestType.modifyPassword, token: token);
required UserIdentity identity,
required token
}): _identity = identity, super(type: TCPRequestType.modifyPassword, token: token);
@override
Map<String, Object?> get body => {
'username': _username,
'passwd': _oldPassword,
'newPasswd': _newPassword
};
Map<String, Object?> get body => _identity.jsonObject;
}
class ModifyProfileRequest extends TCPRequest {
final int _userid;
final String _username;
final String _avatar;
final UserInfo _userinfo;
const ModifyProfileRequest ({
required int userid, //Note: This can be fetched from local_service_repository
required String username,
required String avatar,
required UserInfo userInfo,
required int token
}):
_userid = userid,
_username = username,
_avatar = avatar,
super(type: TCPRequestType.modifyProfile, token: token);
}): _userinfo = userInfo, super(type: TCPRequestType.modifyProfile, token: token);
@override
Map<String, Object?> get body => {
'userid': _userid,
'username': _username,
'avatar': _avatar
};
Map<String, Object?> get body => _userinfo.jsonObject;
}
class SendMessageRequest extends TCPRequest {
final int _userid;
final int _targetid;
final MessageType _contenttype;
final String _content;
final int _timestamp;
late final String _contentmd5;
final LocalFile? _payload;
final Message _message;
SendMessageRequest({
required int userid,
required int targetid,
required MessageType contenttype,
required String content,
LocalFile? payload,
required Message message,
required int token
}):
_userid = userid,
_targetid = targetid,
_contenttype = contenttype,
_content = base64.encode(utf8.encode(content)),
_timestamp = DateTime.now().millisecondsSinceEpoch,
_payload = payload,
super(type: TCPRequestType.sendMessage, token: token) {
_contentmd5 = md5.convert(
utf8.encode(content)
..addAll(Uint8List(4)..buffer.asInt32List()[0] = userid)
..addAll(Uint8List(4)..buffer.asInt32List()[0] = targetid)
..addAll(Uint8List(4)..buffer.asInt32List()[0] = _timestamp)
).toString();
}
_message = message,
super(type: TCPRequestType.sendMessage, token: token);
@override
Map<String, Object?> get body => {
'userid': _userid,
'targetid': _targetid,
'contenttype': _contenttype.literal,
'content': _content,
'timestamp': _timestamp,
'md5Encoded': _contentmd5,
'filemd5': _payload?.filemd5
};
Map<String, Object?> get body => _message.jsonObject;
LocalFile? get payload => _payload;
Message get message => _message;
}
class FetchMessageRequest extends TCPRequest {

View File

@ -0,0 +1,246 @@
/*
* @Author : Linloir
* @Date : 2022-10-11 11:02:19
* @LastEditTime : 2022-10-11 16:00:53
* @Description :
*/
import 'package:tcp_client/repositories/common_models/message.dart';
import 'package:tcp_client/repositories/common_models/userinfo.dart';
import 'package:tcp_client/repositories/file_repository/models/local_file.dart';
enum TCPResponseType {
token ('TOKEN'), //Only exists when server is sending message
checkState ('STATE'), //Check login state for device token
register ('REGISTER'), //Register new user
login ('LOGIN'), //Login via username and password
logout ('LOGOUT'), //Logout for current device token
profile ('PROFILE'), //Fetch current logged in user profile
modifyPassword('MODIFYPASSWD'), //Modify user password
modifyProfile ('MODIFYPROFILE'), //Modify user profile
sendMessage ('SENDMSG'), //Send message
forwardMessage('FORWARDMSG'), //Forward message
fetchMessage ('FETCHMSG'), //Fetch message
findFile ('FINDFILE'), //Find file by md5 before transmitting the file
fetchFile ('FETCHFILE'), //Fetch file and file md5 by message md5
searchUser ('SEARCHUSR'), //Search username and userid by username
addContact ('ADDCONTACT'), //Add one-way relation to a user
fetchContact ('FETCHCONTACT'), //Fetch all contacts, including requesting and pending
unknown ('UNKNOWN'); //Wrong command
const TCPResponseType(String value): _value = value;
final String _value;
String get value => _value;
//Construct the enum type by value
factory TCPResponseType.fromValue(String value) {
return TCPResponseType.values.firstWhere((element) => element._value == value, orElse: () => TCPResponseType.unknown);
}
}
enum TCPResponseStatus {
ok ('OK'),
err ('ERR'),
unknown ('UNKNOWN');
const TCPResponseStatus(String value): _value = value;
final String _value;
String get value => _value;
//Construct the enum type by value
factory TCPResponseStatus.fromValue(String value) {
return TCPResponseStatus.values.firstWhere((element) => element._value == value, orElse: () => TCPResponseStatus.unknown);
}
}
abstract class TCPResponse {
late final TCPResponseType _type;
late final TCPResponseStatus _status;
late final String? _info;
TCPResponse({
required Map<String, Object?> jsonObject
}) {
_type = TCPResponseType.fromValue(jsonObject['response'] as String);
_status = TCPResponseStatus.fromValue(jsonObject['status'] as String);
_info = jsonObject['info'] as String?;
}
TCPResponseType get type => _type;
TCPResponseStatus get status => _status;
String? get info => _info;
}
class SetTokenReponse extends TCPResponse {
final int _token;
SetTokenReponse({
required Map<String, Object?> jsonObject
}):
_token = (jsonObject['body'] as Map<String, Object?>)['tokenid'] as int,
super(jsonObject: jsonObject);
int get token => _token;
}
class CheckStateResponse extends TCPResponse {
late final UserInfo _userInfo;
CheckStateResponse({
required Map<String, Object?> jsonObject
}): super(jsonObject: jsonObject) {
_userInfo = UserInfo.fromJSONObject(jsonObject: jsonObject['body'] as Map<String, Object?>);
}
UserInfo get userInfo => _userInfo;
}
class RegisterResponse extends TCPResponse {
late final UserInfo _userInfo;
RegisterResponse({
required Map<String, Object?> jsonObject
}): super(jsonObject: jsonObject) {
_userInfo = UserInfo.fromJSONObject(jsonObject: jsonObject['body'] as Map<String, Object?>);
}
UserInfo get userInfo => _userInfo;
}
class LoginResponse extends TCPResponse {
late final UserInfo _userInfo;
LoginResponse({
required Map<String, Object?> jsonObject
}): super(jsonObject: jsonObject) {
_userInfo = UserInfo.fromJSONObject(jsonObject: jsonObject['body'] as Map<String, Object?>);
}
UserInfo get userInfo => _userInfo;
}
class LogoutResponse extends TCPResponse {
LogoutResponse({
required Map<String, Object?> jsonObject
}): super(jsonObject: jsonObject);
}
class GetProfileResponse extends TCPResponse {
late final UserInfo _userInfo;
GetProfileResponse({
required Map<String, Object?> jsonObject
}): super(jsonObject: jsonObject) {
_userInfo = UserInfo.fromJSONObject(jsonObject: jsonObject['body'] as Map<String, Object?>);
}
UserInfo get userInfo => _userInfo;
}
class ModifyPasswordResponse extends TCPResponse {
ModifyPasswordResponse({
required Map<String, Object?> jsonObject
}): super(jsonObject: jsonObject);
}
class ModifyProfileResponse extends TCPResponse {
late final UserInfo _userInfo;
ModifyProfileResponse({
required Map<String, Object?> jsonObject
}): super(jsonObject: jsonObject) {
_userInfo = UserInfo.fromJSONObject(jsonObject: jsonObject['body'] as Map<String, Object?>);
}
UserInfo get userInfo => _userInfo;
}
class SendMessageResponse extends TCPResponse {
SendMessageResponse({
required Map<String, Object?> jsonObject
}): super(jsonObject: jsonObject);
}
class ForwardMessageResponse extends TCPResponse {
late final Message _message;
ForwardMessageResponse({
required Map<String, Object?> jsonObject
}): super(jsonObject: jsonObject) {
_message = Message.fromJSONObject(jsonObject: jsonObject['body'] as Map<String, Object?>);
}
Message get message => _message;
}
class FetchMessageResponse extends TCPResponse {
late final List<Message> _messages;
FetchMessageResponse({
required Map<String, Object?> jsonObject
}): super(jsonObject: jsonObject) {
_messages = ((jsonObject['body'] as Map<String, Object?>)['messages'] as List)
.map((e) => Message.fromJSONObject(jsonObject: e)).toList();
}
List<Message> get messages => _messages;
}
class FindFileResponse extends TCPResponse {
FindFileResponse({
required Map<String, Object?> jsonObject
}): super(jsonObject: jsonObject);
bool get foundIdentical => status == TCPResponseStatus.ok;
}
class FetchFileResponse extends TCPResponse {
final LocalFile _payload;
FetchFileResponse({
required Map<String, Object?> jsonObject,
required LocalFile payload
}): _payload = payload, super(jsonObject: jsonObject);
LocalFile get payload => _payload;
}
class SearchUserResponse extends TCPResponse {
late final UserInfo _userInfo;
SearchUserResponse({
required Map<String, Object?> jsonObject
}): super(jsonObject: jsonObject) {
_userInfo = UserInfo.fromJSONObject(jsonObject: jsonObject['body'] as Map<String, Object?>);
}
UserInfo get userInfo => _userInfo;
}
class AddContactResponse extends TCPResponse {
AddContactResponse({
required Map<String, Object?> jsonObject
}): super(jsonObject: jsonObject);
}
class FetchContactResponse extends TCPResponse {
late final List<UserInfo> _added;
late final List<UserInfo> _pending;
late final List<UserInfo> _requesting;
FetchContactResponse({
required Map<String, Object?> jsonObject
}): super(jsonObject: jsonObject) {
var body = jsonObject['body'] as Map<String, Object?>;
var rawAddedContacts = body['contacts'] as List;
var rawPendingContacts = body['pending'] as List;
var rawRequestingContacts = body['requesting'] as List;
_added = rawAddedContacts.map((e) => UserInfo.fromJSONObject(jsonObject: e)).toList();
_pending = rawPendingContacts.map((e) => UserInfo.fromJSONObject(jsonObject: e)).toList();
_requesting = rawRequestingContacts.map((e) => UserInfo.fromJSONObject(jsonObject: e)).toList();
}
List<UserInfo> get addedContacts => _added;
List<UserInfo> get pendingContacts => _pending;
List<UserInfo> get requestingContacts => _requesting;
}