I was trying to fetch market tickers from Google Finance but I am getting the same value over time. Below is my code, any fix? Its giving same output $2,254.84 again and again.
import 'dart:io' as io;
import 'dart:convert';
import 'package:puppeteer/puppeteer.dart' as pp;
void main() async {
var launch = await pp.puppeteer.launch(
executablePath: "/usr/bin/brave-browser",
);
print(await launch.version);
var stocks_nasdaq = ["GOOG", "MSFT", "APPL", "TESLA"];
var page = await launch.newPage();
while (true) {
for (var asset in stocks_nasdaq) {
await page.goto("https://www.google.com/finance/quote/$asset:NASDAQ");
var kk = ["c_p", "24h", "p_year"].iterator;
var aa = ((await page.$$eval("div.P6K39c",
'function (el) { var eee=[];for(var a=0;a<el.length;a++){eee[a]=el[a].innerHTML; } return eee; }')));
for (var a in aa) {
if (a.contains("\$")) {
kk.moveNext();
print({
asset: {kk.current: a}
});
}
}
io.sleep(Duration(seconds: 10));
}
}
}
Related
How can I await a stream (or any other event queue) multiple times?
I tried Stream.first & Stream.single, both doesn't work.
What I want to do:
//next is a fake member
Future<void> xxx() async {
final eventStream = foo();
await eventStream.next; // wait for first event
//do some work
await eventStream.next; // wait for second event
//do some other differnet work
await eventStream.next; // wait for 3rd event
// another differnet work
return;
}
equvalent to:
Future<void> xxx() async {
final eventStream = foo();
int i=0;
await for (final _ in eventStream){
if(i==0);//do some work
else if(i==1);//do some other differnet work
else if(i==2){;break;}//another differnet work
++i;
}
return;
}
Try StreamQueue from package:async.
var q = StreamQueue(eventStream);
var v1 = await q.next;
var v2 = await q.next;
var v3 = await q.next;
// other work.
await q.cancel(); // If not listened to completely yet.
I end up with a custom class
class CompleterQueue<T> {
final _buf = <Completer<T>>[];
var _iWrite = 0;
var _iRead = 0;
int get length => _buf.length;
Future<T> next() {
if (_iRead == _buf.length) {
_buf.add(Completer<T>());
}
final fut = _buf[_iRead].future;
_iRead += 1;
_cleanup();
return fut;
}
void add(T val) {
if (_iWrite == _buf.length) {
final prm = Completer<T>();
_buf.add(prm);
}
_buf[_iWrite].complete(val);
_iWrite += 1;
_cleanup();
}
void _cleanup() {
final minI = _iWrite < _iRead ? _iWrite : _iRead;
if (minI > 0) {
_buf.removeRange(0, minI);
_iWrite -= minI;
_iRead -= minI;
}
}
}
I want to mix MediaStreamTrack objects in Dart using the package:universal_html/js.dart library.
JsAudioContext audioContext = JsAudioContext();
audioContext.initialize();
var senders = await call!.peerConnection!.getSenders();
for (var sender in senders) {
for (var track in senderTracks) {
if (sender.track!.id != track.id) {
audioContext.connect(track);
}
}
}
But WebRtc hides the jsTrack native object inside the MediaStreamTrackWeb object.
How can I access this object ?
Is there anyone have an idea ?
I found the solution using the js_bindings library.
The library's MediaStream.getTracks() method throws a type error.
I solved this problem using js_util interop.
JsAudioContext.dart:
import 'dart:convert';
import 'package:flutter_webrtc/flutter_webrtc.dart' as webrtc;
import 'package:dart_webrtc/src/media_stream_track_impl.dart' as track_impl;
import 'package:js_bindings/js_bindings.dart' as js_bindings;
import 'package:universal_html/html.dart' as html;
import 'dart:js_util' as js_util;
class JsAudioContext {
js_bindings.AudioContext? audioContext;
js_bindings.MediaStreamAudioDestinationNode? destinationNode;
JsAudioContext() {
audioContext = js_bindings.AudioContext();
}
void createMediaStreamDestination() {
destinationNode = audioContext?.createMediaStreamDestination();
}
void connect(webrtc.MediaStreamTrack? trackWeb) {
track_impl.MediaStreamTrackWeb mediaStreamTrackWeb =
trackWeb as track_impl.MediaStreamTrackWeb;
html.MediaStreamTrack htmlTrack = mediaStreamTrackWeb.jsTrack;
var sourceStream = audioContext?.createMediaStreamSource(
js_bindings.MediaStream([htmlTrack as js_bindings.MediaStreamTrack]));
sourceStream?.connect(destinationNode!);
}
webrtc.MediaStreamTrack getMixedTrack() {
List<dynamic> outputTrack =
js_util.callMethod(destinationNode!.stream, 'getTracks', []);
webrtc.MediaStreamTrack rtcTrack = track_impl.MediaStreamTrackWeb(
outputTrack.toList()[0] as html.MediaStreamTrack);
return rtcTrack;
}
}
sip_call_event_service.dart:
#override
Future startConference(List<SipCallData> activeCallList) async {
List<webrtc.MediaStreamTrack> receivedTracks = <webrtc.MediaStreamTrack>[];
for (var item in activeCallList) {
Call? call = sipuaHelper!.findCall(item.id!);
var receives = await call!.peerConnection!.getReceivers();
for (var element in receives) {
receivedTracks.add(element.track!);
}
}
JsAudioContext jsAudioContext = JsAudioContext();
for (var item in activeCallList) {
Call? call = sipuaHelper!.findCall(item.id!);
jsAudioContext.createMediaStreamDestination();
var receivers = await call!.peerConnection!.getReceivers();
for (var receiver in receivers) {
for (var track in receivedTracks) {
if (receiver.track!.id != track.id) {
jsAudioContext.connect(track);
}
}
}
var senders = await call.peerConnection!.getSenders();
for (var sender in senders) {
jsAudioContext.connect(sender.track);
}
await senders.first.replaceTrack(jsAudioContext.getMixedTrack());
}
}
I was trying to create a function to make a GET with query parameters. I was dealing with the Mangadex API and was to send a parameter called 'manga' as an array. I created the code as follows:
Future<http.Response> getCoverArtResponse(String mangaID) async {
var queryParameters = {
'limit': '10',
'manga': [mangaID] //Here
};
var unencodedPath = '/cover';
var response = await http.get(
Uri.https(authority, unencodedPath, queryParameters),
headers: {HttpHeaders.contentTypeHeader: 'application/json'});
return response;
}
However, the response was the following error:
{"result":"error","errors":[{"id":"9c346772-7b14-5982-b4b6-7b5888522762","status":400,"title":"validation_exception","detail":"Error validating \/manga: String value found, but an array is required","context":null}]}
How am I supposed to send the parameters? So far I have tried -
'manga': [mangaID]
'manga': '[$mangaID]'
None of them seem to work.
import 'dart:async';
import 'package:wnetworking/wnetworking.dart';
class MangaDex {
static const _base = 'https://api.mangadex.org';
static FutureOr<void> _getter({required String url, required Function(JMap item, int idx) onItem}) async {
await HttpReqService.getJson<JMap>(url)
.then((response) {
var results = response?['results'];
if (results != null) {
if (results is List) {
var i = 0;
results.forEach((manga) => onItem(manga, ++i));
} else {
print(response);
}
}
});
}
static FutureOr<void> cover({int limit = 10, int offset=0, String? mangaId, String? coverId}) async {
final mangas = mangaId != null ? '&manga[]=$mangaId' : '';
final covers = coverId != null ? '&ids[]=$coverId' : '';
final url = '$_base/cover?limit=$limit&offset=$offset$mangas$covers';
await _getter(
url: url,
onItem: (item, idx) {
print('$idx) "${item['data']?['attributes']?['fileName']}"');
print(' id: ${item['data']?['id']}\n');
},
);
}
}
void main(List<String> args) async {
await MangaDex.cover(mangaId: '32d76d19-8a05-4db0-9fc2-e0b0648fe9d0', limit: 2);
print('\nJob done');
}
Result:
1) "f5873770-80a4-470e-a11c-63b709d87eb3.jpg"
id: b6c7ce9c-e671-4f26-90b0-e592188e9cd6
2) "e9f926db-b469-48c4-8cc4-a8e523ad75ca.jpg"
id: 00aae6e0-46bb-4f92-a82a-1c740789b704
Job done
Replace wnetworking package with http package, and JMap with Map<String, dynamic>
NOTE: MangaDex Documentation is lacking and misleading about how to correctly use its endpoints.
I am trying to upload image from client (flutter) to server (Aqueduct.io) using MultipartRequest.
It's working, but currently file names are assigned the current time, how can I pass the filename from a client and parse it on a server side?
Client code:
final String imageName = nameController.text.replaceAll(" ", "");
var postUri = Uri.parse("http://***:8888/media");
var request = new http.MultipartRequest("POST", postUri);
request.files.add(new http.MultipartFile.fromBytes('file', image,
filename: imageName, contentType: MediaType('image', 'jpeg')));
request.send().then((response) {
if (response.statusCode == 200) print("Uploaded!");
});
}
Server code:
import 'dart:async';
import 'dart:io';
import 'package:aqueduct/aqueduct.dart';
import 'package:mime/mime.dart';
import 'package:http_server/http_server.dart';
class MediaController extends ResourceController {
MediaController() {
acceptedContentTypes = [ContentType("multipart", "form-data")];
}
#Operation.post()
Future<Response> postMultipartForm() async {
final transformer = MimeMultipartTransformer(
request.raw.headers.contentType.parameters["boundary"]);
final bodyStream =
Stream.fromIterable([await request.body.decode<List<int>>()]);
final parts = await transformer.bind(bodyStream).toList();
for (var part in parts) {
final HttpMultipartFormData multipart = HttpMultipartFormData.parse(part);
final content = multipart.cast<List<int>>();
final filePath =
"public/" + DateTime.now().millisecondsSinceEpoch.toString() + ".jpg"; // <---current filename implementation
final IOSink sink = File(filePath).openWrite();
await for (List<int> item in content) {
sink.add(item);
}
await sink.flush();
await sink.close();
}
return Response.ok({});
}
}
Okay, I have the asnwer
import 'dart:async';
import 'dart:io';
import 'package:aqueduct/aqueduct.dart';
import 'package:mime/mime.dart';
import 'package:http_server/http_server.dart';
class MediaController extends ResourceController {
MediaController() {
acceptedContentTypes = [ContentType("multipart", "form-data")];
}
#Operation.post()
Future<Response> postMultipartForm() async {
final transformer = MimeMultipartTransformer(
request.raw.headers.contentType.parameters["boundary"]);
final bodyStream =
Stream.fromIterable([await request.body.decode<List<int>>()]);
final parts = await transformer.bind(bodyStream).toList();
for (var part in parts) {
final HttpMultipartFormData multipart = HttpMultipartFormData.parse(part);
List<String> tokens = part.headers['content-disposition'].split(";");
String filename;
for (var i = 0; i < tokens.length; i++) {
if (tokens[i].contains('filename')) {
filename = tokens[i]
.substring(tokens[i].indexOf("=") + 2, tokens[i].length - 1);
}
}
print('file $filename.jpg uploaded');
final content = multipart.cast<List<int>>();
final filePath =
// "public/" + DateTime.now().millisecondsSinceEpoch.toString() + ".jpg";
'public/$filename.jpg';
final IOSink sink = File(filePath).openWrite();
await for (List<int> item in content) {
sink.add(item);
}
await sink.flush();
await sink.close();
}
return Response.ok({});
}
}
I have already try to understand the API doc, the articles about them, and this post: How do you create a Stream in Dart
I'm making a simple web app using WebSocket. Actually, it's working well, but I want add a feature (enjoy learn).
This is my class (can be optimized I guess)
library Ask;
import 'dart:html';
import 'dart:async';
import 'dart:convert';
class Ask {
final String addr;
String _protocol;
String _port;
WebSocket _ws;
bool openned;
Map<int, Completer> _completer_list = {};
int _counter = 0;
static final Map<String, Ask> _cache = <String, Ask>{};
factory Ask(String addr) {
if (_cache.containsKey(addr)) {
return _cache[addr];
} else {
final ask_server = new Ask._internal(addr);
_cache[addr] = ask_server;
return ask_server;
}
}
Ask._internal(this.addr);
Future<bool> open() {
if (openned)
return true;
_completer_list[0] = new Completer();
if (window.location.protocol == 'http:') {
_port = ':8080/ws';
_protocol = 'ws://';
} else {
_port = ':8443/ws';
_protocol = 'wss://';
}
_ws = new WebSocket(_protocol + addr + _port);
_ws.onOpen.listen((e) {
_get_data();
_get_close();
openned = true;
_completer_list[0].complete(true);
});
return _completer_list[0].future;
}
Future<String> send(Map data) {
bool check = false;
int id;
_completer_list.forEach((k, v) {
if (v.isCompleted) {
id = data['ws_id'] = k;
_completer_list[k] = new Completer();
_ws.send(JSON.encode(data));
check = true;
}
});
if (!check) {
_counter++;
id = data['ws_id'] = _counter;
_completer_list[id] = new Completer();
_ws.send(JSON.encode(data));
}
return _completer_list[id].future;
}
void _get_data() {
_ws.onMessage.listen((MessageEvent data) {
var response = JSON.decode(data.data);
_completer_list[response['ws_id']].complete(response);
});
}
void _get_close() {
_ws.onClose.listen((_) {
print('Server have been lost. Try to reconnect in 3 seconds.');
new Timer(new Duration(seconds: 3), () {
_ws = new WebSocket(_protocol + addr + _port);
_get_data();
_get_close();
_ws.onOpen.listen((e) => print('Server is alive again.'));
});
});
}
}
Example of use:
void showIndex() {
Element main = querySelector('main');
Ask connect = new Ask('127.0.0.1');
Map request = {};
request['index'] = true;
connect.open().then((_) {
connect.send(request).then((data) {
main.setInnerHtml(data['response']);
});
});
}
I would replace the then by a listen who will be canceled when the message will completed. By this way, I can add a progress bar, I think...
So my question, my send function can be a stream and keep my concept of one websocket for all ? (yes, if my function is used when a request is in progress, it's sent and if she's finish before the first, I recovered her properly. Thank you ws_id).
Thank you.
I think what you need is a StreamController
https://api.dartlang.org/apidocs/channels/stable/dartdoc-viewer/dart-async.StreamController