dimsdk 2.3.2 copy "dimsdk: ^2.3.2" to clipboard
dimsdk: ^2.3.2 copied to clipboard

Decentralized Instant Messaging Software Development Kit.

Decentralized Instant Messaging (Dart SDK) #

License PRs Welcome Platform Issues Repo Size Tags Version

Watchers Forks Stars Followers

Dependencies #

  • Latest Versions
Name Version Description
Ming Ke Ming (名可名) Version Decentralized User Identity Authentication
Dao Ke Dao (道可道) Version Universal Message Module
DIMP (去中心化通讯协议) Version Decentralized Instant Messaging Protocol

Extensions #

Content #

extends CustomizedContent

ContentProcessor #

///  Customized Content Processing Unit
///  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
///  Handle content for application customized
class CustomizedContentProcessor extends BaseContentProcessor {
  CustomizedContentProcessor(super.facebook, super.messenger);

  @override
  Future<List<Content>> processContent(Content content, ReliableMessage rMsg) async {
    assert(content is CustomizedContent, 'customized content error: $content');
    CustomizedContent customized = content as CustomizedContent;
    var filter = sharedMessageExtensions.customizedFilter;
    // get handler for 'app' & 'mod'
    CustomizedContentHandler handler = filter.filterContent(content, rMsg);
    // handle the action
    return await handler.handleAction(customized, rMsg, messenger!);
  }

}
  • CustomizedContentHandler
///  Handler for Customized Content
///  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
abstract interface class CustomizedContentHandler {

  ///  Do your job
  ///
  /// @param content   - customized content
  /// @param rMsg      - network message
  /// @param messenger - message transceiver
  /// @return responses
  Future<List<Content>> handleAction(CustomizedContent content, ReliableMessage rMsg, Messenger messenger);

}

/// Default Handler
/// ~~~~~~~~~~~~~~~
class BaseCustomizedContentHandler implements CustomizedContentHandler {

  @override
  Future<List<Content>> handleAction(CustomizedContent content, ReliableMessage rMsg, Messenger messenger) async {
    // String app = content.application;
    String app = content.getString('app') ?? '';
    String mod = content.module;
    String act = content.action;
    String text = 'Content not support.';
    return respondReceipt(text, content: content, envelope: rMsg.envelope, extra: {
      'template': 'Customized content (app: \${app}, mod: \${mod}, act: \${act}) not support yet!',
      'replacements': {
        'app': app,
        'mod': mod,
        'act': act,
      }
    });
  }

  //
  //  Convenient responding
  //

  // protected
  List<ReceiptCommand> respondReceipt(String text, {
    required Envelope envelope, Content? content, Map<String, Object>? extra
  }) => [
    // create base receipt command with text & original envelope
    BaseContentProcessor.createReceipt(text, envelope: envelope, content: content, extra: extra)
  ];

}
  • CustomizedContentFilter
/// Factory for CustomizedContentHandler
abstract interface class CustomizedContentFilter {

  ///  Get CustomizedContentHandler for the CustomizedContent
  ///
  /// @param content - customized content
  /// @param rMsg    - network message
  /// @return CustomizedContentHandler
  CustomizedContentHandler filterContent(CustomizedContent content, ReliableMessage rMsg);

}


/// CustomizedContent Extensions
/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~

CustomizedContentFilter _filter = AppCustomizedFilter();

extension CustomizedContentExtension on MessageExtensions {

  CustomizedContentFilter get customizedFilter => _filter;
  set customizedFilter(CustomizedContentFilter filter) => _filter = filter;

}


/// General CustomizedContent Filter
/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
class AppCustomizedFilter implements CustomizedContentFilter {

  CustomizedContentHandler defaultHandler = BaseCustomizedContentHandler();

  final Map<String, CustomizedContentHandler> _handlers = {};

  void setContentHandler({
    required String app, required String mod,
    required CustomizedContentHandler handler
  }) => _handlers['$app:$mod'] = handler;

  // protected
  CustomizedContentHandler? getContentHandler({
    required String app, required String mod,
  }) => _handlers['$app:$mod'];

  @override
  CustomizedContentHandler filterContent(CustomizedContent content, ReliableMessage rMsg) {
    // String app = content.application;
    String app = content.getString('app') ?? '';
    String mod = content.module;
    var handler = getContentHandler(app: app, mod: mod);
    if (handler != null) {
      return handler;
    }
    // if the application has too many modules, I suggest you to
    // use different handler to do the jobs for each module.
    throw defaultHandler;
  }

}
  • Example for group querying
/*  Command Transform:

    +===============================+===============================+
    |      Customized Content       |      Group Query Command      |
    +-------------------------------+-------------------------------+
    |   "type" : i2s(0xCC)          |   "type" : i2s(0x88)          |
    |   "sn"   : 123                |   "sn"   : 123                |
    |   "time" : 123.456            |   "time" : 123.456            |
    |   "app"  : "chat.dim.group"   |                               |
    |   "mod"  : "history"          |                               |
    |   "act"  : "query"            |                               |
    |                               |   "command"   : "query"       |
    |   "group"     : "{GROUP_ID}"  |   "group"     : "{GROUP_ID}"  |
    |   "last_time" : 0             |   "last_time" : 0             |
    +===============================+===============================+
 */
class GroupHistoryHandler extends BaseCustomizedContentHandler {

  @override
  Future<List<Content>> handleAction(CustomizedContent content, ReliableMessage rMsg, Messenger messenger) async {
    if (content.group == null) {
      assert(false, 'group command error: $content, sender: ${rMsg.sender}');
      String text = 'Group command error.';
      return respondReceipt(text, envelope: rMsg.envelope, content: content);
    }
    String act = content.action;
    if (act == GroupHistory.ACT_QUERY) {
      // assert(GroupHistory.APP == content.application);
      assert(GroupHistory.MOD == content.module);
      return await transformQueryCommand(content, rMsg, messenger);
    }
    assert(false, 'unknown action: $act, $content, sender: ${rMsg.sender}');
    return await super.handleAction(content, rMsg, messenger);
  }

  // private
  Future<List<Content>> transformQueryCommand(CustomizedContent content, ReliableMessage rMsg, Messenger messenger) async {
    Map info = content.copyMap(false);
    info['type'] = ContentType.COMMAND;
    info['command'] = QueryCommand.QUERY;
    Content? query = Content.parse(info);
    if (query is QueryCommand) {
      return await messenger.processContent(query, rMsg);
    }
    assert(false, 'query command error: $query, $content, sender: ${rMsg.sender}');
    String text = 'Query command error.';
    return respondReceipt(text, envelope: rMsg.envelope, content: content);
  }

}


//  void registerCustomizedHandlers() {
//    var filter = AppCustomizedFilter();
//    // 'chat.dim.group:history'
//    filter.setContentHandler(
//      app: GroupHistory.APP,
//      mod: GroupHistory.MOD,
//      handler: GroupHistoryHandler(),
//    );
//    sharedMessageExtensions.customizedFilter = filter;
//  }

ContentProcessorCreator #

import 'package:dimsdk/dimsdk.dart';

import 'customized.dart';
import 'handshake.dart';


class ClientContentProcessorCreator extends BaseContentProcessorCreator {
  ClientContentProcessorCreator(super.facebook, super.messenger);

  @override
  ContentProcessor? createContentProcessor(String msgType) {
    switch (msgType) {

      // application customized
      case ContentType.APPLICATION:
      case ContentType.CUSTOMIZED:
        return CustomizedContentProcessor(facebook!, messenger!);

      // ...
    }
    // others
    return super.createContentProcessor(msgType);
  }

  @override
  ContentProcessor? createCommandProcessor(String msgType, String cmd) {
    switch (cmd) {
    
      case HandshakeCommand.HANDSHAKE:
        return HandshakeCommandProcessor(facebook!, messenger!);
        
      // ...
    }
    // others
    return super.createCommandProcessor(msgType, cmd);
  }

}

Usage #

To let your AppCustomizedProcessor start to work, you must override BaseContentProcessorCreator for message types:

  1. ContentType.APPLICATION
  2. ContentType.CUSTOMIZED

and then set your creator for GeneralContentProcessorFactory in the MessageProcessor.


Copyright © 2023-2026 Albert Moky Followers

1
likes
140
points
488
downloads

Publisher

verified publisherdim.chat

Weekly Downloads

Decentralized Instant Messaging Software Development Kit.

Repository (GitHub)
View/report issues

Documentation

API reference

License

MIT (license)

Dependencies

dimp

More

Packages that depend on dimsdk