mirror of
https://github.com/hkalexling/Mango.git
synced 2026-04-25 00:00:52 -04:00
461398d219
* Add "title_title" to slim JSON * WIP * WIP * WIP * WIP * Add plugin subscription types * Revert "Subscription manager" This reverts commita612500b0f. * Use auto overflow tables cherry-picked froma612500b0f* Add endpoint for plugin subscription * WIP * WIP * Simplify subscription JSON parsing * Remove MangaDex files that are no longer needed * Fix linter * Refactor date filtering and use native date picker * Delete unnecessary raise for debugging * Subscription management API endpoints * Store manga ID with subscriptions * Add subscription manager page (WIP) * Finish subscription manager page * WIP * Finish plugin updater * Base64 encode chapter IDs * Fix actions on download manager * Trigger subscription update from manager page * Fix timestamp precision issue in plugin * Show target API version * Update last checked from manager page * Update last checked even when no chapters found * Fix null pid * Clean up * Document the subscription endpoints * Fix BigFloat conversion issue * Confirmation before deleting subscriptions * Reset table sort options * Show manga title on subscription manager
116 lines
2.5 KiB
Crystal
116 lines
2.5 KiB
Crystal
require "uuid"
|
|
require "big"
|
|
|
|
enum FilterType
|
|
String
|
|
NumMin
|
|
NumMax
|
|
DateMin
|
|
DateMax
|
|
Array
|
|
|
|
def self.from_string(str)
|
|
case str
|
|
when "string"
|
|
String
|
|
when "number-min"
|
|
NumMin
|
|
when "number-max"
|
|
NumMax
|
|
when "date-min"
|
|
DateMin
|
|
when "date-max"
|
|
DateMax
|
|
when "array"
|
|
Array
|
|
else
|
|
raise "Unknown filter type with string #{str}"
|
|
end
|
|
end
|
|
end
|
|
|
|
struct Filter
|
|
include JSON::Serializable
|
|
|
|
property key : String
|
|
property value : String | Int32 | Int64 | Float32 | Nil
|
|
property type : FilterType
|
|
|
|
def initialize(@key, @value, @type)
|
|
end
|
|
|
|
def self.from_json(str) : Filter
|
|
json = JSON.parse str
|
|
key = json["key"].as_s
|
|
type = FilterType.from_string json["type"].as_s
|
|
_value = json["value"]
|
|
value = _value.as_s? || _value.as_i? || _value.as_i64? ||
|
|
_value.as_f32? || nil
|
|
self.new key, value, type
|
|
end
|
|
|
|
def match_chapter(obj : JSON::Any) : Bool
|
|
return true if value.nil? || value.to_s.empty?
|
|
raw_value = obj[key]
|
|
case type
|
|
when FilterType::String
|
|
raw_value.as_s.downcase == value.to_s.downcase
|
|
when FilterType::NumMin, FilterType::DateMin
|
|
BigFloat.new(raw_value.as_s) >= BigFloat.new value.not_nil!.to_f32
|
|
when FilterType::NumMax, FilterType::DateMax
|
|
BigFloat.new(raw_value.as_s) <= BigFloat.new value.not_nil!.to_f32
|
|
when FilterType::Array
|
|
return true if value == "all"
|
|
raw_value.as_s.downcase.split(",")
|
|
.map(&.strip).includes? value.to_s.downcase.strip
|
|
else
|
|
false
|
|
end
|
|
end
|
|
end
|
|
|
|
# We use class instead of struct so we can update `last_checked` from
|
|
# `SubscriptionList`
|
|
class Subscription
|
|
include JSON::Serializable
|
|
|
|
property id : String
|
|
property plugin_id : String
|
|
property manga_id : String
|
|
property manga_title : String
|
|
property name : String
|
|
property created_at : Int64
|
|
property last_checked : Int64
|
|
property filters = [] of Filter
|
|
|
|
def initialize(@plugin_id, @manga_id, @manga_title, @name)
|
|
@id = UUID.random.to_s
|
|
@created_at = Time.utc.to_unix
|
|
@last_checked = Time.utc.to_unix
|
|
end
|
|
|
|
def match_chapter(obj : JSON::Any) : Bool
|
|
filters.all? &.match_chapter(obj)
|
|
end
|
|
end
|
|
|
|
struct SubscriptionList
|
|
@dir : String
|
|
@path : String
|
|
|
|
getter ary = [] of Subscription
|
|
|
|
forward_missing_to @ary
|
|
|
|
def initialize(@dir)
|
|
@path = Path[@dir, "subscriptions.json"].to_s
|
|
if File.exists? @path
|
|
@ary = Array(Subscription).from_json File.read @path
|
|
end
|
|
end
|
|
|
|
def save
|
|
File.write @path, @ary.to_pretty_json
|
|
end
|
|
end
|