Skip to content

Commit a6d95d8

Browse files
committed
List visits
1 parent 760b404 commit a6d95d8

File tree

4 files changed

+121
-4
lines changed

4 files changed

+121
-4
lines changed

CHANGELOG.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
## 0.4.0
22

3-
-
3+
- List visits
44

55
## 0.3.0
66

lib/shlink.dart

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,3 +4,6 @@ export 'src/shlink_base.dart';
44
export 'src/shlink_exception.dart';
55
export 'src/dto/create_short_url.dart';
66
export 'src/dto/short_url.dart';
7+
export 'src/dto/meta.dart';
8+
export 'src/dto/visit.dart';
9+
export 'src/enums/order_field.dart';

lib/src/dto/visit.dart

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
import 'package:shlink/shlink.dart';
2+
3+
class Visit {
4+
final String referer;
5+
final DateTime date;
6+
final String userAgent;
7+
final VisitLocation visitLocation;
8+
9+
Visit._(this.referer, this.date, this.userAgent, this.visitLocation);
10+
11+
factory Visit.fromJson(Map mJson) {
12+
String referer = mJson['referer'];
13+
DateTime date = DateTime.parse(mJson['date']);
14+
String userAgent = mJson['userAgent'];
15+
VisitLocation visitLocation;
16+
17+
if (mJson.containsKey('visitLocation') && mJson['visitLocation'] != null) {
18+
visitLocation = VisitLocation.fromJson(mJson['visitLocation']);
19+
}
20+
21+
return Visit._(referer, date, userAgent, visitLocation);
22+
}
23+
24+
@override
25+
String toString() =>
26+
'Visit{referer=$referer;date=$date;userAgent=$userAgent;visitLocation=$visitLocation}';
27+
}
28+
29+
class VisitLocation {
30+
final String cityName;
31+
final String countryCode;
32+
final String countryName;
33+
final String latitude;
34+
final String longitude;
35+
final String regionName;
36+
final String timezone;
37+
38+
VisitLocation._(this.cityName, this.countryCode, this.countryName,
39+
this.latitude, this.longitude, this.regionName, this.timezone);
40+
41+
factory VisitLocation.fromJson(Map mJson) {
42+
return VisitLocation._(
43+
mJson['cityName'],
44+
mJson['countryCode'],
45+
mJson['countryName'],
46+
mJson['latitude'],
47+
mJson['longitude'],
48+
mJson['regionName'],
49+
mJson['timezone']);
50+
}
51+
52+
@override
53+
String toString() =>
54+
'VisitLocation{cityName=$cityName;countryCode=$countryCode;countryName=$countryName;latitude=$latitude;longitude=$longitude;regionName=$regionName;timezone=$timezone}';
55+
}

lib/src/shlink_base.dart

Lines changed: 62 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import 'shlink_exception.dart';
55
import 'dto/create_short_url.dart';
66
import 'dto/meta.dart';
77
import 'dto/short_url.dart';
8+
import 'dto/visit.dart';
89
import 'enums/order_field.dart';
910
import 'extension/datetime.dart';
1011

@@ -212,9 +213,7 @@ class Shlink {
212213
Map<String, dynamic> mShortUrls = mJson['shortUrls'];
213214

214215
List<dynamic> lstData = mShortUrls['data'];
215-
for (dynamic data in lstData) {
216-
lstShortUrls.add(ShortUrl.fromJson(data));
217-
}
216+
lstShortUrls.addAll(lstData.map((u) => ShortUrl.fromJson(u)).toList());
218217

219218
Map<String, dynamic> mPagination = mShortUrls['pagination'];
220219
if (mPagination['pagesCount'] > mPagination['currentPage']) {
@@ -334,4 +333,64 @@ class Shlink {
334333
String sBody = await utf8.decoder.bind(response).single;
335334
throw ShlinkException.fromJson(response.statusCode, sBody);
336335
}
336+
337+
/// List the visits of [shortCode] within [startDate] and [endDate]
338+
Future<List<Visit>> listVisits(String shortCode,
339+
{DateTime startDate, DateTime endDate}) async {
340+
return _listVisits(1, shortCode, startDate, endDate);
341+
}
342+
343+
/// Internal visit list method
344+
Future<List<Visit>> _listVisits(
345+
int iPage, String shortCode, DateTime startDate, DateTime endDate) async {
346+
String sUrl = '$_url$_API_PATH/short-urls/${shortCode}/visits?page=$iPage';
347+
348+
if (_domain != null && _domain.isNotEmpty) {
349+
sUrl += '&domain=$_domain';
350+
}
351+
352+
// Start Date
353+
if (startDate != null) {
354+
sUrl +=
355+
'&startDate=${Uri.encodeQueryComponent(startDate.toIso8601StringShlink())}';
356+
}
357+
358+
// End Date
359+
if (endDate != null) {
360+
sUrl +=
361+
'&endDate=${Uri.encodeQueryComponent(endDate.toIso8601StringShlink())}';
362+
}
363+
364+
List<Visit> lstVisits = <Visit>[];
365+
366+
HttpClientRequest request = await HttpClient().getUrl(Uri.parse(sUrl))
367+
..headers.contentType = ContentType.json
368+
..headers.set(_HEADER_API_KEY, _apiKey);
369+
370+
HttpClientResponse response = await request.close();
371+
372+
if (response.statusCode == 404) {
373+
return null;
374+
}
375+
376+
String sBody = await utf8.decoder.bind(response).single;
377+
378+
if (response.statusCode != 200) {
379+
throw ShlinkException.fromJson(response.statusCode, sBody);
380+
}
381+
382+
Map<String, dynamic> mJson = jsonDecode(sBody);
383+
Map<String, dynamic> mVisits = mJson['visits'];
384+
385+
List<dynamic> lstVisitsJson = mVisits['data'];
386+
lstVisits.addAll(lstVisitsJson.map((v) => Visit.fromJson(v)).toList());
387+
388+
Map<String, dynamic> mPagination = mVisits['pagination'];
389+
if (mPagination['pagesCount'] > mPagination['currentPage']) {
390+
lstVisitsJson
391+
.addAll(await _listVisits(iPage + 1, shortCode, startDate, endDate));
392+
}
393+
394+
return lstVisits;
395+
}
337396
}

0 commit comments

Comments
 (0)