CLI interface to medialist (fossil mirror)
Révision | 4834f05a1af7763170476aab0d60231569fa3fdd (tree) |
---|---|
l'heure | 2022-01-20 15:39:41 |
Auteur | mio <stigma@disr...> |
Commiter | mio |
fix startDate being erroneously changed.
FossilOrigin-Name: 932a14e1c296859ed00552eb0498f9e47220def2e2ccde9adb902721cf1748db
@@ -70,13 +70,13 @@ enum MLCommand | ||
70 | 70 | delete_, |
71 | 71 | /** |
72 | 72 | * Update an item on a list. |
73 | - * | |
73 | + * | |
74 | 74 | * Args: ["Item ID", "field::value", "field::value", ...] |
75 | - * | |
75 | + * | |
76 | 76 | * For example: ml_send_command(list, MLCommand.update, ["1", "status:READING"]); |
77 | 77 | * The "field" is automatically converted to lowercase, while the value is kept |
78 | 78 | * as-is. |
79 | - * | |
79 | + * | |
80 | 80 | * To update the start and end date of an item, use "start_date" and |
81 | 81 | * "end_date" respectively. |
82 | 82 | */ |
@@ -592,30 +592,30 @@ private MLError _ml_update(MediaList* list, string[] args) | ||
592 | 592 | |
593 | 593 | if (2 > args.length) |
594 | 594 | return MLError.invalidArgs; |
595 | - | |
595 | + | |
596 | 596 | string title = null; |
597 | 597 | string progress = null; |
598 | 598 | string status = null; |
599 | 599 | string startDate = ""; |
600 | 600 | string endDate = ""; |
601 | - | |
601 | + | |
602 | 602 | size_t id; |
603 | - | |
603 | + | |
604 | 604 | try { |
605 | 605 | id = to!size_t(args[0]); |
606 | 606 | } catch (Exception e) { |
607 | 607 | return MLError.invalidArgs; |
608 | 608 | } |
609 | - | |
609 | + | |
610 | 610 | foreach(string arg; args) { |
611 | 611 | string[] kv = arg.split("::"); |
612 | 612 | |
613 | 613 | if (2 > kv.length) |
614 | 614 | continue; |
615 | - | |
615 | + | |
616 | 616 | string k = kv[0].toLower(); |
617 | 617 | string v = kv[1]; |
618 | - | |
618 | + | |
619 | 619 | switch (k) { |
620 | 620 | case "title": |
621 | 621 | title = v; |
@@ -636,11 +636,11 @@ private MLError _ml_update(MediaList* list, string[] args) | ||
636 | 636 | break; |
637 | 637 | } |
638 | 638 | } |
639 | - | |
639 | + | |
640 | 640 | string tempFilePath = buildPath(tempDir, "ml_temp.tsv"); |
641 | 641 | File tempFile = File(tempFilePath, "w+"); |
642 | 642 | scope(exit) remove(tempFilePath); |
643 | - | |
643 | + | |
644 | 644 | int[2][6] headerPositions = _ml_get_header_positions(list); |
645 | 645 | size_t titleIndex = 0; |
646 | 646 | size_t progressIndex = 0; |
@@ -648,7 +648,7 @@ private MLError _ml_update(MediaList* list, string[] args) | ||
648 | 648 | size_t startDateIndex = 0; |
649 | 649 | size_t endDateIndex = 0; |
650 | 650 | size_t lastUpdatedIndex = 0; |
651 | - | |
651 | + | |
652 | 652 | foreach (ref header; headerPositions) { |
653 | 653 | switch (header[0]) { |
654 | 654 | case MLHeaders.title: |
@@ -673,29 +673,29 @@ private MLError _ml_update(MediaList* list, string[] args) | ||
673 | 673 | break; |
674 | 674 | } |
675 | 675 | } |
676 | - | |
676 | + | |
677 | 677 | File listFile = File(list.filePath, "r"); |
678 | 678 | list.isOpen = true; |
679 | - | |
679 | + | |
680 | 680 | string line; |
681 | 681 | bool pastHeader; |
682 | 682 | size_t currentIndex = 1; |
683 | - | |
683 | + | |
684 | 684 | while ((line = listFile.readln()) !is null) { |
685 | 685 | if (line.length == 0) |
686 | 686 | continue; |
687 | - | |
687 | + | |
688 | 688 | if (line[0] == '#') { |
689 | 689 | tempFile.write(line); |
690 | 690 | continue; |
691 | 691 | } |
692 | - | |
692 | + | |
693 | 693 | if (false == pastHeader) { |
694 | 694 | pastHeader = true; |
695 | 695 | tempFile.write(line); |
696 | 696 | continue; |
697 | 697 | } |
698 | - | |
698 | + | |
699 | 699 | if (currentIndex == id) { |
700 | 700 | string[] sections = line.strip().split("\t"); |
701 | 701 | if (title !is null) |
@@ -705,20 +705,20 @@ private MLError _ml_update(MediaList* list, string[] args) | ||
705 | 705 | |
706 | 706 | if (status !is null) { |
707 | 707 | string oldStatus = sections[statusIndex]; |
708 | - | |
708 | + | |
709 | 709 | if ((oldStatus.toLower == "plan-to-read" && status == "reading") || |
710 | 710 | (oldStatus.toLower == "plan-to-watch" && status == "watching")) { |
711 | - | |
711 | + | |
712 | 712 | if (startDate == "") { |
713 | 713 | Date date = cast(Date)Clock.currTime; |
714 | 714 | startDate = format!"%d-%02d-%02d"(date.year, date.month, date.day); |
715 | 715 | sections[startDateIndex] = startDate; |
716 | 716 | } |
717 | 717 | } |
718 | - | |
718 | + | |
719 | 719 | if ((oldStatus.toLower == "reading" && status == "complete") || |
720 | 720 | (oldStatus.toLower == "watching" && status == "complete")) { |
721 | - | |
721 | + | |
722 | 722 | if (endDate == "") { |
723 | 723 | Date date = cast(Date)Clock.currTime; |
724 | 724 | endDate = format!"%d-%02d-%02d"(date.year, date.month, date.day); |
@@ -729,33 +729,33 @@ private MLError _ml_update(MediaList* list, string[] args) | ||
729 | 729 | sections[statusIndex] = status; |
730 | 730 | } |
731 | 731 | |
732 | - if (startDate !is null) | |
732 | + if (startDate != "") | |
733 | 733 | sections[startDateIndex] = startDate; |
734 | - if (endDate !is null) | |
734 | + if (endDate != "") | |
735 | 735 | sections[endDateIndex] = endDate; |
736 | - | |
736 | + | |
737 | 737 | Date date = cast(Date)Clock.currTime(); |
738 | 738 | sections[lastUpdatedIndex] = format!"%d-%02d-%02d"(date.year, date.month, date.day); |
739 | 739 | tempFile.writeln(join(sections, "\t")); |
740 | 740 | } else { |
741 | 741 | tempFile.write(line); |
742 | 742 | } |
743 | - | |
743 | + | |
744 | 744 | currentIndex += 1; |
745 | 745 | } |
746 | - | |
746 | + | |
747 | 747 | listFile.close(); |
748 | 748 | tempFile.flush(); |
749 | 749 | tempFile.close(); |
750 | - | |
750 | + | |
751 | 751 | tempFile = File(tempFilePath, "r"); |
752 | 752 | listFile = File(list.filePath, "w+"); |
753 | - | |
753 | + | |
754 | 754 | while ((line = tempFile.readln()) !is null) { |
755 | 755 | listFile.write(line); |
756 | 756 | } |
757 | 757 | listFile.flush(); |
758 | - | |
758 | + | |
759 | 759 | list.isOpen = false; |
760 | 760 | |
761 | 761 | return MLError.success; |
@@ -1392,39 +1392,39 @@ private bool unittest_updateItemTitle() | ||
1392 | 1392 | { |
1393 | 1393 | enum listName = __FUNCTION__; |
1394 | 1394 | enum fileName = listName ~ ".tsv"; |
1395 | - | |
1395 | + | |
1396 | 1396 | MediaList* list = ml_open_list(fileName); |
1397 | 1397 | if (list is null) { |
1398 | 1398 | diag("ml_open_list returned null."); |
1399 | 1399 | return false; |
1400 | 1400 | } |
1401 | - | |
1401 | + | |
1402 | 1402 | scope(exit) { |
1403 | 1403 | ml_send_command(list, MLCommand.delete_, []); |
1404 | 1404 | ml_free_list(list); |
1405 | 1405 | } |
1406 | - | |
1406 | + | |
1407 | 1407 | MLError res; |
1408 | - | |
1408 | + | |
1409 | 1409 | res = ml_send_command(list, MLCommand.add, ["Ietm 1"]); |
1410 | 1410 | if (MLError.success != res) { |
1411 | 1411 | diag("ml_send_command(list, add, [Ietm 1]) failed."); |
1412 | 1412 | return false; |
1413 | 1413 | } |
1414 | - | |
1414 | + | |
1415 | 1415 | res = ml_send_command(list, MLCommand.update, ["1", "title::Item 1"]); |
1416 | 1416 | if (MLError.success != res) { |
1417 | 1417 | diag("Failed to send UPDATE command [1, title::Item 1]."); |
1418 | 1418 | return false; |
1419 | 1419 | } |
1420 | - | |
1420 | + | |
1421 | 1421 | MediaListItem item; |
1422 | 1422 | res = ml_fetch_item(list, 1, &item); |
1423 | 1423 | if (MLError.success != res) { |
1424 | 1424 | diag("Failed to fetch item 1 from list."); |
1425 | 1425 | return false; |
1426 | 1426 | } |
1427 | - | |
1427 | + | |
1428 | 1428 | if ("Item 1" != item.title) { |
1429 | 1429 | diag("Failed to update title from 'Ietm 1' to 'Item 1'."); |
1430 | 1430 | return false; |
@@ -1437,39 +1437,39 @@ private bool unittest_updateItemStatus() | ||
1437 | 1437 | { |
1438 | 1438 | enum listName = __FUNCTION__; |
1439 | 1439 | enum fileName = listName ~ ".tsv"; |
1440 | - | |
1440 | + | |
1441 | 1441 | MediaList* list = ml_open_list(fileName); |
1442 | 1442 | if (list is null) { |
1443 | 1443 | diag("ml_open_list returned null."); |
1444 | 1444 | return false; |
1445 | 1445 | } |
1446 | - | |
1446 | + | |
1447 | 1447 | scope(exit) { |
1448 | 1448 | ml_send_command(list, MLCommand.delete_, []); |
1449 | 1449 | ml_free_list(list); |
1450 | 1450 | } |
1451 | - | |
1451 | + | |
1452 | 1452 | MLError res; |
1453 | - | |
1453 | + | |
1454 | 1454 | res = ml_send_command(list, MLCommand.add, ["Item 1", null, "PLAN-TO-READ"]); |
1455 | 1455 | if (MLError.success != res) { |
1456 | 1456 | diag("ml_send_command(list, add, [Item 1, null, PLAN-TO-READ]) failed."); |
1457 | 1457 | return false; |
1458 | 1458 | } |
1459 | - | |
1459 | + | |
1460 | 1460 | res = ml_send_command(list, MLCommand.update, ["1", "status::READING"]); |
1461 | 1461 | if (MLError.success != res) { |
1462 | 1462 | diag("Failed to send UPDATE command [1, status::READING]."); |
1463 | 1463 | return false; |
1464 | 1464 | } |
1465 | - | |
1465 | + | |
1466 | 1466 | MediaListItem item; |
1467 | 1467 | res = ml_fetch_item(list, 1, &item); |
1468 | 1468 | if (MLError.success != res) { |
1469 | 1469 | diag("Failed to fetch item 1 from list."); |
1470 | 1470 | return false; |
1471 | 1471 | } |
1472 | - | |
1472 | + | |
1473 | 1473 | if ("READING" != item.status) { |
1474 | 1474 | diag("Failed to update status from 'PLAN-TO-READ' to 'READING'."); |
1475 | 1475 | return false; |
@@ -1482,39 +1482,39 @@ private bool unittest_updateItemProgress() | ||
1482 | 1482 | { |
1483 | 1483 | enum listName = __FUNCTION__; |
1484 | 1484 | enum fileName = listName ~ ".tsv"; |
1485 | - | |
1485 | + | |
1486 | 1486 | MediaList* list = ml_open_list(fileName); |
1487 | 1487 | if (list is null) { |
1488 | 1488 | diag("ml_open_list returned null."); |
1489 | 1489 | return false; |
1490 | 1490 | } |
1491 | - | |
1491 | + | |
1492 | 1492 | scope(exit) { |
1493 | 1493 | ml_send_command(list, MLCommand.delete_, []); |
1494 | 1494 | ml_free_list(list); |
1495 | 1495 | } |
1496 | - | |
1496 | + | |
1497 | 1497 | MLError res; |
1498 | - | |
1498 | + | |
1499 | 1499 | res = ml_send_command(list, MLCommand.add, ["Item 1"]); |
1500 | 1500 | if (MLError.success != res) { |
1501 | 1501 | diag("ml_send_command(list, add, [Item 1]) failed."); |
1502 | 1502 | return false; |
1503 | 1503 | } |
1504 | - | |
1504 | + | |
1505 | 1505 | res = ml_send_command(list, MLCommand.update, ["1", "progress::10/10"]); |
1506 | 1506 | if (MLError.success != res) { |
1507 | 1507 | diag("Failed to send UPDATE command [1, progress::10/10]."); |
1508 | 1508 | return false; |
1509 | 1509 | } |
1510 | - | |
1510 | + | |
1511 | 1511 | MediaListItem item; |
1512 | 1512 | res = ml_fetch_item(list, 1, &item); |
1513 | 1513 | if (MLError.success != res) { |
1514 | 1514 | diag("Failed to fetch item 1 from list."); |
1515 | 1515 | return false; |
1516 | 1516 | } |
1517 | - | |
1517 | + | |
1518 | 1518 | if ("10/10" != item.progress) { |
1519 | 1519 | diag("Failed to update progress from '-/-' to '10/10'."); |
1520 | 1520 | return false; |
@@ -1527,26 +1527,26 @@ private bool unittest_updateItemAll() | ||
1527 | 1527 | { |
1528 | 1528 | enum listName = __FUNCTION__; |
1529 | 1529 | enum fileName = listName ~ ".tsv"; |
1530 | - | |
1530 | + | |
1531 | 1531 | MediaList* list = ml_open_list(fileName); |
1532 | 1532 | if (list is null) { |
1533 | 1533 | diag("ml_open_list returned null."); |
1534 | 1534 | return false; |
1535 | 1535 | } |
1536 | - | |
1536 | + | |
1537 | 1537 | scope(exit) { |
1538 | 1538 | ml_send_command(list, MLCommand.delete_, []); |
1539 | 1539 | ml_free_list(list); |
1540 | 1540 | } |
1541 | - | |
1541 | + | |
1542 | 1542 | MLError res; |
1543 | - | |
1543 | + | |
1544 | 1544 | res = ml_send_command(list, MLCommand.add, ["Ietm 1"]); |
1545 | 1545 | if (MLError.success != res) { |
1546 | 1546 | diag("ml_send_command(list, add, [Ietm 1]) failed."); |
1547 | 1547 | return false; |
1548 | 1548 | } |
1549 | - | |
1549 | + | |
1550 | 1550 | res = ml_send_command(list, MLCommand.update, |
1551 | 1551 | ["1", |
1552 | 1552 | "start_date::2021-02-16", |
@@ -1559,24 +1559,24 @@ private bool unittest_updateItemAll() | ||
1559 | 1559 | diag("Failed to send UPDATE command."); |
1560 | 1560 | return false; |
1561 | 1561 | } |
1562 | - | |
1562 | + | |
1563 | 1563 | MediaListItem item; |
1564 | 1564 | res = ml_fetch_item(list, 1, &item); |
1565 | 1565 | if (MLError.success != res) { |
1566 | 1566 | diag("Failed to fetch item 1 from list."); |
1567 | 1567 | return false; |
1568 | 1568 | } |
1569 | - | |
1569 | + | |
1570 | 1570 | if ("MediaList" != item.title) { |
1571 | 1571 | diag("Failed to update item title from 'Ietm 1' to 'MediaList'."); |
1572 | 1572 | return false; |
1573 | 1573 | } |
1574 | - | |
1574 | + | |
1575 | 1575 | if ("60/100" != item.progress) { |
1576 | 1576 | diag("Failed to update progress from '-/-' to '60/100'."); |
1577 | 1577 | return false; |
1578 | 1578 | } |
1579 | - | |
1579 | + | |
1580 | 1580 | if ("READING" != item.status) { |
1581 | 1581 | diag("Failed to update status from 'UNKNOWN' to 'READING'."); |
1582 | 1582 | return false; |
@@ -1586,12 +1586,12 @@ private bool unittest_updateItemAll() | ||
1586 | 1586 | diag("Failed to update start_date from '' to '2021-02-16'."); |
1587 | 1587 | return false; |
1588 | 1588 | } |
1589 | - | |
1589 | + | |
1590 | 1590 | if ("2022-01-20" != item.endDate) { |
1591 | 1591 | diag("Failed to update end_date from '' to '2022-01-20'."); |
1592 | 1592 | return false; |
1593 | 1593 | } |
1594 | - | |
1594 | + | |
1595 | 1595 | Date date = cast(Date)Clock.currTime; |
1596 | 1596 | string currentDate = format!"%d-%02d-%02d"(date.year, date.month, date.day); |
1597 | 1597 | if (currentDate != item.lastUpdated) { |