123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149 |
- /*
- * pixiv_down - CLI-based downloading tool for https://www.pixiv.net.
- * Copyright (C) 2024 Mio
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, version 3 of the License.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <https://www.gnu.org/licenses/>.
- */
- module pd.utils;
- import std.net.curl : HTTP;
- /// User Agent header that is used for requests to www.pixiv.net.
- enum UserAgent = "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/17.6 Safari/605.1.1";
- /// Create a `std.net.curl.HTTP` client prepared for requests to pixiv.
- ///
- /// Params:
- /// phpsessid = The PHPSESSID cookie value.
- /// headers = Custom headers to use for this request.
- ///
- /// There are some default headers that will be used if they're not
- /// present in `headers`:
- ///
- /// * `accept: application/json, */*`
- /// * `host: www.pixiv.net`
- /// * `referer: https://www.pixiv.net`
- ///
- /// Returns: A HTTP client with the appropriate headers set for making
- /// requests to the pixiv servers.
- HTTP makeHTTPClient(string phpsessid, string[string] headers = string[string].init)
- {
- import std.experimental.logger: warningf;
- auto client = HTTP();
- headers.require("accept", "application/json, */*");
- headers.require("host", "www.pixiv.net");
- headers.require("referer", "https://www.pixiv.net");
- foreach(const ref header, const ref value; headers) {
- client.addRequestHeader(header, value);
- }
- client.onReceiveStatusLine = (HTTP.StatusLine statusLine) {
- if (statusLine.code < 200 || statusLine.code > 299) {
- // Shame you can't access the URL for the client...
- warningf("Received non-200 status code %d (%s)", statusLine.code, statusLine.reason);
- }
- };
- client.setCookie("PHPSESSID=" ~ phpsessid);
- client.setUserAgent(UserAgent);
- return client;
- }
- ///
- /// Attempt to make *path* safe for different operating systems.
- ///
- /// This will replace anything that is not: a hyphen ('-'), a period ('.'),
- /// an underscore ('_'), or a "word character" (includes numbers). Any
- /// characters found will be replaced by a hyphen.
- ///
- /// Only tested on Linux and Android.
- ///
- /// Params:
- /// path = The input path to replace characters with.
- ///
- /// Returns: A new string with the replacements made.
- ///
- string makeSafe(string path)
- {
- import std.regex : regex, replaceAll;
- import std.string : chomp, replace, strip;
- enum kReplacement = "-";
- // 2.076 compat: reg must not be 'const'. Doesn't work with replaceAll.
- auto reg = regex(`[^-\w._]`);
- const noSpaces = strip(path).replace(" ", kReplacement);
- const almostSafe = replaceAll(noSpaces, reg, kReplacement);
- return chomp(almostSafe, "._-");
- }
- /**
- * Suspend the current thread for a random value between *lowest* and
- * *largest*.
- *
- * Params:
- * lowest = The lowest value to use for the random sleep duration.
- * largest = The largest value to use for the random sleep duration.
- * print = Print a message to `stderr` with sleep duration.
- */
- void sleep(int lowest, int largest, bool print = true)
- {
- import core.thread : Thread;
- import core.time : seconds;
- import std.random : Random, uniform, unpredictableSeed;
- auto seed = Random(unpredictableSeed);
- const secs = uniform(lowest, largest + 1, seed);
- if (print) {
- import std.stdio : stderr;
- stderr.writefln("Sleeping for %d seconds...", secs);
- }
- Thread.sleep(secs.seconds);
- }
- struct StopSpinnerMessage {}
- void runSpinner(string prefix)
- {
- import core.time : msecs;
- import core.thread : Thread;
- import std.concurrency : receiveTimeout;
- import std.stdio : stderr;
- import mlib.term;
- const delay = 100.msecs;
- const segments = ['|', '/', '-', '\\'];
- bool running = true;
- while (running) {
- for (auto i = 0; i < segments.length; ++i) {
- receiveTimeout(1.msecs,
- (StopSpinnerMessage _) {
- running = false;
- return;
- }
- );
- if (!running) {
- break;
- }
- stderr.writef("\r\033[2K%s %c", prefix, segments[i]);
- stderr.flush();
- Thread.sleep(delay);
- }
- }
- }
|