ethanblake4 / dart_eval

Extensible Dart interpreter for Dart with full interop
https://pub.dev/packages/dart_eval
BSD 3-Clause "New" or "Revised" License
334 stars 40 forks source link

cannot invoke async function of a bridge class without extending it #151

Closed Noobware1 closed 11 months ago

Noobware1 commented 11 months ago

for some reason every time I try to invoke the extract method of the GogoCDN class It throws this weird error

Unhandled exception:
Stack Overflow
#0      checkValidWeakTarget (dart:_internal-patch/internal_patch.dart:211:1)
#1      Expando.[] (dart:core-patch/expando_patch.dart:31:5)
#2      $Bridge.$_invoke (package:dart_eval/src/eval/bridge/runtime_bridge.dart:44:39)
#3      $GogoCDN.extract (package:meiyou_extenstions/src/extractors/gogo_cdn/gogo_cdn.eval.dart:86:30)
#4      $GogoCDN.$bridgeGet.<anonymous closure> (package:meiyou_extenstions/src/extractors/gogo_cdn/gogo_cdn.eval.dart:76:26)

I don't see what Im doing wrong I mean it compiles even returns the instance and the name getter and extractor link also work only the extract method throws this error.

gogo_cdn.dart

import 'dart:convert';

import 'package:crypto_dart/crypto_dart.dart';
import 'package:meiyou_extenstions/meiyou_extenstions.dart';
import 'package:meiyou_extenstions/src/utils/client.dart';
import 'package:ok_http_dart/ok_http_dart.dart';

class GogoCDN extends ExtractorApi {
  GogoCDN(super.extractorLink);

  @override
  String get name => 'GogoCDN';

  @override
  Future<Video> extract() async {
    final doc = (await client.get(extractorLink.url)).document;
    final script =
        doc.selectFirst('script[data-name="episode"]').attr('data-value');
    final id = doc.selectFirst('#id').attr('value');
    final host = Uri.parse(extractorLink.url).host;
    final encryptedID = _cryptoHandler(_keysAndIV.key, _keysAndIV.iv, id, true);
    final decryptedID = _cryptoHandler(_keysAndIV.key, _keysAndIV.iv, script)
        .replaceFirst(id, encryptedID);

    final encryptedData = (await client.get(
            'https://$host/encrypt-ajax.php?id=$decryptedID&alias=$id',
            headers: {'x-requested-with': 'XMLHttpRequest'}))
        .json((json) => json['data'] as String);

    final decryptedData = _SourceResponse.fromJson(jsonDecode(
        _cryptoHandler(_keysAndIV.secondKey, _keysAndIV.iv, encryptedData)));

    final List<VideoSource> list = [];

    final headers = {'referer': 'https://$host'};

    Future<void> addVideo(_Source source, [bool? backup]) async {
      final label = source.label.toLowerCase();
      final url = source.file;
      if (label != "auto p" && label != "hls p") {
        list.add(VideoSource(
          url: url,
          quality: VideoQuality.getFromString(label),
          format: VideoFormat.other,
          isBackup: backup ?? false,
        ));
      } else {
        list.add(VideoSource(
          url: url,
          format: VideoFormat.hls,
          quality: VideoQuality.hlsMaster,
          isBackup: backup ?? false,
        ));
      }
    }

    for (final e in decryptedData.source) {
      await addVideo(e);
    }
    if (decryptedData.backup != null) {
      for (final e in decryptedData.backup!) {
        await addVideo(e, true);
      }
    }
    return Video(videoSources: list, headers: headers);
  }

  static const _keysAndIV = _Keys('37911490979715163134003223491201',
      '54674138327930866480207815084989', '3134003223491201');

  String _cryptoHandler(String key, String iv, String text,
      [bool encrypt = false]) {
    final options = CipherOptions(
        ivEncoding: 'utf8',
        keyEncoding: 'utf8',
        textEncoding: encrypt ? 'utf8' : 'base64');
    if (encrypt) {
      return CryptoDart.AES
          .encrypt(text, key, iv: iv, options: options)
          .toString();
    } else {
      return CryptoDart.AES
          .decrypt(text, key, iv: iv, options: options)
          .convertToString(CryptoDart.enc.utf8);
    }
  }
}

class _Keys {
  final String key;
  final String secondKey;
  final String iv;

  const _Keys(this.key, this.secondKey, this.iv);
}

class _SourceResponse {
  final List<_Source> source;
  final List<_Source>? backup;

  _SourceResponse(this.source, this.backup);

  factory _SourceResponse.fromJson(dynamic json) {
    return _SourceResponse(
      (json['source'] as List).mapAsList(_Source.fromJson),
      (json['source_bk'] as List?)?.mapAsList(_Source.fromJson),
    );
  }
}

class _Source {
  final String file;
  final String label;
  final String type;

  _Source({required this.label, required this.file, required this.type});

  factory _Source.fromJson(dynamic json) {
    return _Source(
        label: json['label'], file: json['file'], type: json['type']);
  }
}

gogo_cdn.eval.dart

import 'package:dart_eval/dart_eval.dart';
import 'package:dart_eval/dart_eval_bridge.dart';
import 'package:dart_eval/stdlib/core.dart';
import 'package:meiyou_extenstions/src/bridge_models/extractor_link.dart';
import 'package:meiyou_extenstions/src/bridge_models/interfaces/extractor_api.dart';
import 'package:meiyou_extenstions/src/bridge_models/media/video/video.dart';
import 'package:meiyou_extenstions/src/constants/constants.dart';
import 'package:meiyou_extenstions/src/extractors/gogo_cdn/gogo_cdn.dart';
import 'package:meiyou_extenstions/src/models/media/video/video.dart';

class $GogoCDN extends GogoCDN with $Bridge<GogoCDN> {
  $GogoCDN(super.extractorLink);

  static void configureForRuntime(Runtime runtime) {
    runtime.registerBridgeFunc(bridgeLibary, 'GogoCDN.', $GogoCDN.$new,
        isBridge: true);
  }

  static const $type = BridgeTypeRef(BridgeTypeSpec(bridgeLibary, 'GogoCDN'));

  static const $declaration = BridgeClassDef(
      BridgeClassType($type, isAbstract: false, $extends: $ExtractorApi.$type),
      constructors: {
        '': BridgeConstructorDef(
          BridgeFunctionDef(
            returns: BridgeTypeAnnotation($type),
            generics: {},
            namedParams: [],
            params: [
              BridgeParameter('extractorLink',
                  BridgeTypeAnnotation($ExtractorLink.$type), false)
            ],
          ),
        )
      },
      methods: {
        'extract': BridgeMethodDef(
          BridgeFunctionDef(
            returns: BridgeTypeAnnotation(
                BridgeTypeRef(CoreTypes.future, [$Video.$type])),
          ),
        )
      },
      fields: {
        'extractorLink':
            BridgeFieldDef(BridgeTypeAnnotation($ExtractorLink.$type))
      },
      getters: {
        'name': BridgeMethodDef(
          BridgeFunctionDef(
              returns: BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.string))),
          isStatic: false,
        )
      },
      bridge: true);

  static $Value? $new(Runtime runtime, $Value? target, List<$Value?> args) {
    return $GogoCDN(args[0]?.$value);
  }

  @override
  $Value? $bridgeGet(String identifier) {
    switch (identifier) {
      case 'name':
        return $String(super.name);
      case 'extractorLink':
        return $ExtractorLink.wrap(super.extractorLink);
      case 'extract':
        return $Function((runtime, target, args) =>
            $Future.wrap(extract().then((value) => $Video.wrap(value))));
      default:
        return const $null();
    }
  }

  @override
  void $bridgeSet(String identifier, $Value value) {}

  @override
  Future<Video> extract() => $_invoke('extract', []);

  @override
  String get name => $_get('name');
}

here's how i am calling it

  final compiled = ExtenstionComplier().compilePackages({
    'meiyou': {
      'main.dart': '''
import 'package:meiyou_extenstions/meiyou_extenstions.dart';

main() {
  return GogoCDN(ExtractorLink(name: '', url: 'https://goone.pro/embedplus?id=MjE2NjE5&token=ClWxZf1yKiawvQxLJ5p4Yw&expires=1701853917'));
}

''',
    }
  });
  final value = ExtenstionLoader()
      .runtimeEval(compiled)
      .executeLib('package:meiyou/main.dart', 'main') as $RapidCloud;

  print(await value.extract());
ethanblake4 commented 11 months ago

Well I guess you figured it out but for anyone who comes across this, I believe you need to do super.extract instead of just extract in $bridgeGet.

Noobware1 commented 11 months ago

Thanks for the reply, I did figured it out and I also checked if it works if I extend in inside eval and it still works!!