import 'dart:async'; import 'dart:convert'; import 'dart:io'; import 'dart:typed_data'; import 'package:fake_weibo/src/domain/api/weibo_user_info_resp.dart'; import 'package:fake_weibo/src/domain/sdk/weibo_auth_resp.dart'; import 'package:fake_weibo/src/domain/sdk/weibo_sdk_resp.dart'; import 'package:flutter/services.dart'; import 'package:meta/meta.dart'; class Weibo { static const String _METHOD_REGISTERAPP = 'registerApp'; static const String _METHOD_ISWEIBOINSTALLED = 'isWeiboInstalled'; static const String _METHOD_AUTH = 'auth'; static const String _METHOD_SHARETEXT = 'shareText'; static const String _METHOD_SHAREIMAGE = 'shareImage'; static const String _METHOD_SHAREWEBPAGE = 'shareWebpage'; static const String _METHOD_ONAUTHRESP = 'onAuthResp'; static const String _METHOD_ONSHAREMSGRESP = 'onShareMsgResp'; static const String _ARGUMENT_KEY_APPKEY = 'appKey'; static const String _ARGUMENT_KEY_SCOPE = 'scope'; static const String _ARGUMENT_KEY_REDIRECTURL = 'redirectUrl'; static const String _ARGUMENT_KEY_TEXT = 'text'; static const String _ARGUMENT_KEY_TITLE = 'title'; static const String _ARGUMENT_KEY_DESCRIPTION = 'description'; static const String _ARGUMENT_KEY_THUMBDATA = 'thumbData'; static const String _ARGUMENT_KEY_IMAGEDATA = 'imageData'; static const String _ARGUMENT_KEY_WEBPAGEURL = 'webpageUrl'; static const String _DEFAULT_REDIRECTURL = 'https://api.weibo.com/oauth2/default.html'; static const MethodChannel _channel = MethodChannel('v7lin.github.io/fake_weibo'); final StreamController _authRespStreamController = StreamController.broadcast(); final StreamController _shareMsgRespStreamController = StreamController.broadcast(); Future registerApp({ @required String appKey, @required List scope, String redirectUrl = _DEFAULT_REDIRECTURL, // 新浪微博开放平台 -> 我的应用 -> 应用信息 -> 高级信息 -> OAuth2.0授权设置 }) { assert(appKey != null && appKey.isNotEmpty); assert(scope != null && scope.isNotEmpty); _channel.setMethodCallHandler(_handleMethod); return _channel.invokeMethod( _METHOD_REGISTERAPP, { _ARGUMENT_KEY_APPKEY: appKey, _ARGUMENT_KEY_SCOPE: scope.join(','), _ARGUMENT_KEY_REDIRECTURL: redirectUrl, }, ); } Future _handleMethod(MethodCall call) async { switch (call.method) { case _METHOD_ONAUTHRESP: _authRespStreamController.add(WeiboAuthRespSerializer() .fromMap(call.arguments as Map)); break; case _METHOD_ONSHAREMSGRESP: _shareMsgRespStreamController.add(WeiboSdkRespSerializer() .fromMap(call.arguments as Map)); break; } } Stream authResp() { return _authRespStreamController.stream; } Stream shareMsgResp() { return _shareMsgRespStreamController.stream; } Future isWeiboInstalled() async { return (await _channel.invokeMethod(_METHOD_ISWEIBOINSTALLED)) as bool; } Future auth({ @required String appKey, @required List scope, String redirectUrl = _DEFAULT_REDIRECTURL, }) { assert(appKey != null && appKey.isNotEmpty); assert(scope != null && scope.isNotEmpty); return _channel.invokeMethod( _METHOD_AUTH, { _ARGUMENT_KEY_APPKEY: appKey, _ARGUMENT_KEY_SCOPE: scope.join(','), _ARGUMENT_KEY_REDIRECTURL: redirectUrl, }, ); } Future getUserInfo({ @required String appkey, @required String userId, @required String accessToken, }) { assert(userId != null && userId.isNotEmpty); assert(accessToken != null && accessToken.isNotEmpty); Map params = { 'uid': userId, }; return HttpClient() .getUrl(_encodeUrl('https://api.weibo.com/2/users/show.json', appkey, accessToken, params)) .then((HttpClientRequest request) { return request.close(); }).then((HttpClientResponse response) async { if (response.statusCode == HttpStatus.ok) { String content = await utf8.decodeStream(response); return WeiboUserInfoRespSerializer() .fromMap(json.decode(content) as Map); } throw HttpException( 'HttpResponse statusCode: ${response.statusCode}, reasonPhrase: ${response.reasonPhrase}.'); }); } Uri _encodeUrl( String baseUrl, String appkey, String accessToken, Map params, ) { params.putIfAbsent('source', () => appkey); params.putIfAbsent('access_token', () => accessToken); Uri baseUri = Uri.parse(baseUrl); Map> queryParametersAll = Map>.of(baseUri.queryParametersAll); params.forEach((String key, String value) { queryParametersAll.remove(key); queryParametersAll.putIfAbsent(key, () => [value]); }); return baseUri.replace(queryParameters: queryParametersAll); } Future shareText({ @required String text, }) { assert(text != null && text.isNotEmpty && text.length <= 1024); return _channel.invokeMethod( _METHOD_SHARETEXT, { _ARGUMENT_KEY_TEXT: text, }, ); } Future shareImage({ @required Uint8List imageData, }) { assert(imageData != null && imageData.lengthInBytes <= 2 * 1024 * 1024); return _channel.invokeMethod( _METHOD_SHAREIMAGE, { _ARGUMENT_KEY_IMAGEDATA: imageData, }, ); } Future shareWebpage({ @required String title, @required String description, @required Uint8List thumbData, @required String webpageUrl, }) { assert(title != null && title.isNotEmpty && title.length <= 512); assert(description != null && description.isNotEmpty && description.length <= 1024); assert(thumbData != null && thumbData.lengthInBytes <= 32 * 1024); assert(webpageUrl != null && webpageUrl.isNotEmpty && webpageUrl.length <= 255); return _channel.invokeMethod( _METHOD_SHAREWEBPAGE, { _ARGUMENT_KEY_TITLE: title, _ARGUMENT_KEY_DESCRIPTION: description, _ARGUMENT_KEY_THUMBDATA: thumbData, _ARGUMENT_KEY_WEBPAGEURL: webpageUrl, }, ); } }