1
Fork 0
mirror of https://github.com/Steffo99/patched-porobot.git synced 2024-12-22 09:34:21 +00:00

Get the bot to working shape, even if with a few bugs

This commit is contained in:
Steffo 2022-08-01 04:22:05 +02:00
parent b14f85022b
commit 1e7230994a
Signed by: steffo
GPG key ID: 6965406171929D01
35 changed files with 76680 additions and 41 deletions

2
.gitignore vendored
View file

@ -1,5 +1,3 @@
/data/
# Generated by Cargo
# will have compiled files and executables
/target/

View file

@ -1,2 +1,26 @@
# patched-porobot
WIP: Legends of Runeterra card bot
## Discord Emoji Codes
```
<:bandle_city:1003469523820744764>
<:beyond_the_bandlewood:1003469815282941983>
<:bilgewater:1003469525565587487>
<:call_of_the_mountain:1003469812191739974>
<:demacia:1003469526874193921>
<:empires_of_the_ascended:1003469813957533726>
<:foundations:1003469809108914296>
<:freljord:1003469528237350962>
<:ionia:1003469529772458094>
<:legends:1003469522432426084>
<:noxus:1003469531068497990>
<:piltover_and_zaun:1003469532444246026>
<:rising_tides:1003469810509820018>
<:runeterra:1003469533706723408>
<:shadow_isles:1003469535078260846>
<:shurima:1003469536990859304>
<:targon:1003469538647613490>
<:worldwalker:1003469816927096914>
```

View file

@ -0,0 +1 @@
Copyright Riot Games, Inc. 2019

View file

@ -0,0 +1,40 @@
metadata.json
{
"locales": ["{string}", ...],
"clientHash": "{string}"
"gameplayDataHash": "{string}",
"timestamp": "{YYYYMMDDhhmm}",
"patchlineRef": "{string}"
}
cards.json
[
{
"id": "{cardCode}",
"idComponents":
{
"set": "setNumber",
"region":
{
"id": "{shortRegionCode}",
"name": "{regionName}"
}
}
"name": "{name}",
"type": "{type}",
"subType": "{subType}",
"superType": "{superType}",
"description": "{description}",
"keywords": [],
"associatedCards": [{cardCode}, ...]
"health": "{health}",
"attack": "{attack}",
"cost": "{cost}",
"assets":
{
"gameAbsolutePath": "http://{cdn}/{bundleName}/set1/en_us/img/card/game/{cardCode}.png"
}
},
{...}
]

View file

@ -0,0 +1,685 @@
{
"vocabTerms": [
{
"description": "When you summon this, it gets its allegiance bonus if the top card of your deck matches its region.",
"name": "Allegiance",
"nameRef": "Allegiance"
},
{
"description": "Pick the next Moon Weapon for Aphelios.",
"name": "Phase",
"nameRef": "Phase"
},
{
"description": "Create a random Blade Fragment still needed to restore the blade. Once youve played all 3, create the Blade of the Exile.",
"name": "Reforge",
"nameRef": "Reforge"
},
{
"description": "Immediately draw 1 of each Ascended ally. For the rest of the game, level 2 Ascended allies are level 3.",
"name": "Restore the Sun Disc",
"nameRef": "SunDiscRestore"
},
{
"description": "Effect when unit strikes with an attack",
"name": "Attack Strike",
"nameRef": "AttackStrike"
},
{
"description": "For each Spawn:\nSummon a 1|1 Tentacle, or if you already have one, grant your strongest Tentacle +1|+1.",
"name": "Spawn",
"nameRef": "Spawn"
},
{
"description": "Highest Power, with ties broken by highest Health then highest Cost.",
"name": "Strongest",
"nameRef": "Strongest"
},
{
"description": "Obliterate X non-champion cards from the bottom of your deck.",
"name": "Toss",
"nameRef": "Toss"
},
{
"description": "Start a free attack with that many summoned Blades.",
"name": "Blade Dance",
"nameRef": "BladeDance"
},
{
"description": "You behold something if you have it in play or hand.",
"name": "Behold",
"nameRef": "Behold"
},
{
"description": "This is how much Mana you need to spend to play this card.",
"name": "Cost",
"nameRef": "Cost"
},
{
"description": "Get this effect when the round ends.",
"name": "Round End",
"nameRef": "RoundEnd"
},
{
"description": "This is how much damage the unit can withstand. If it reaches zero, the unit dies.",
"name": "Health",
"nameRef": "Health"
},
{
"description": "This is how much damage the unit deals when it strikes.",
"name": "Power",
"nameRef": "Power"
},
{
"description": "Get this effect when this unit attacks.",
"name": "Attack",
"nameRef": "Attack"
},
{
"description": "A unit is buffed when its Power or Health is increased or it gains a new keyword.",
"name": "Buffed",
"nameRef": "Buffed"
},
{
"description": "This champion counts as one of your deck's regions. During deckbuilding, you may add the specified cards to your deck regardless of region. Origins may also have an effect that begins at Start of Game.",
"name": "Origin",
"nameRef": "Origin"
},
{
"description": "Get this effect when a unit attempts to deal damage using its Power, either at the end of battle or with spells. Units with 0 Power can't strike.",
"name": "Strike",
"nameRef": "Strike"
},
{
"description": "Effect when unit Strikes the enemy Nexus.",
"name": "Nexus Strike",
"nameRef": "NexusStrike"
},
{
"description": "Activates if allies have struck for 5+ damage at least 4 times this game.",
"name": "Reputation",
"nameRef": "Reputation"
},
{
"description": "Get this effect when the round starts.",
"name": "Round Start",
"nameRef": "RoundStart"
},
{
"description": "The opponent in The Path of Champions.",
"name": "Foe",
"nameRef": "Foe"
},
{
"description": "Get this effect when you play this unit from hand.",
"name": "Play",
"nameRef": "Play"
},
{
"description": "In play, in hand, in deck, in discard, and even if created/summoned later.",
"name": "Everywhere",
"nameRef": "Everywhere"
},
{
"description": "Makes a Countdown landmark count down that many times",
"name": "Advance",
"nameRef": "Advance"
},
{
"description": "Round Start: I count down 1. At 0, activate the Countdown effect, then destroy me.",
"name": "Countdown",
"nameRef": "Countdown"
},
{
"description": "If you don't have one, gain the attack token. You can attack this round.",
"name": "Rally",
"nameRef": "Rally"
},
{
"description": "When you kill a unit via damage, kill effect, or striking it with an ally. (Self-killing, like from Ephemeral, doesn't count.)",
"name": "Slay",
"nameRef": "Slay"
},
{
"description": "Remove all keywords, abilities, and ongoing effects. Doesn't affect damage or subtype.",
"name": "Silence",
"nameRef": "Silence"
},
{
"description": "Create in hand 1 of 3 randomly selected cards.",
"name": "Manifest",
"nameRef": "Manifest"
},
{
"description": "Pick a card from among 3 in your deck. Shuffle the deck and put that card on top.",
"name": "Predict",
"nameRef": "Predict"
}
],
"keywords": [
{
"description": "Inflicts damage beyond what would kill the target(s) to the enemy Nexus.",
"name": "Overwhelm",
"nameRef": "SpellOverwhelm"
},
{
"description": "Can be played whenever you may act. Happens instantly and allows you to continue to play other cards.",
"name": "Burst",
"nameRef": "Burst"
},
{
"description": "Round Start: I count down 1. At 0, activate the Countdown effect, then destroy me.",
"name": "Countdown",
"nameRef": "Countdown"
},
{
"description": "Get this effect when you play this unit from hand.",
"name": "Play",
"nameRef": "PlaySkillMark"
},
{
"description": "Landmarks take up a space on the board. They can't attack, block, or take damage.",
"name": "Landmark",
"nameRef": "LandmarkVisualOnly"
},
{
"description": "A Captured card is removed from the game. It returns when the Capturing unit leaves play.",
"name": "Capture",
"nameRef": "Capture"
},
{
"description": "Get this effect when this unit attacks.",
"name": "Attack",
"nameRef": "AttackSkillMark"
},
{
"description": " ",
"name": "Shurima",
"nameRef": "Shurima"
},
{
"description": "Attach me to an ally to give it my stats and keywords while I'm attached. When that ally leaves play, Recall me.",
"name": "Attach",
"nameRef": "Attach"
},
{
"description": " ",
"name": "Noxus",
"nameRef": "Noxus"
},
{
"description": "Fleeting cards discard from hand when the round ends.",
"name": "Fleeting",
"nameRef": "Fleeting"
},
{
"description": "Missing Translation",
"name": "Missing Translation",
"nameRef": "ClobberNoEmptySlotRequirement"
},
{
"description": "Draw a non-champion card from the bottom of the enemy deck.",
"name": "Nab",
"nameRef": "Nab"
},
{
"description": "Can be played outside combat or when no other spells or skills are pending. Happens instantly and allows you to continue to play other cards.",
"name": "Focus",
"nameRef": "Focus"
},
{
"description": "You're Enlightened when you have 10 max mana.",
"name": "Enlightened",
"nameRef": "Enlightened"
},
{
"description": "Pick a Celestial card from among 3 to create in hand.",
"name": "Invoke",
"nameRef": "Invoke"
},
{
"description": "Attaches to another card in a deck. When that card is drawn, activate the effect.",
"name": "Boon",
"nameRef": "Boon"
},
{
"description": "Attaches to another card in a deck. When that card is drawn, activate the effect.",
"name": "Trap",
"nameRef": "Autoplay"
},
{
"description": "Heal your Nexus for the amount of damage dealt",
"name": "Drain",
"nameRef": "Drain"
},
{
"description": "These abilities take effect when the unit dies.",
"name": "Last Breath",
"nameRef": "LastBreath"
},
{
"description": " ",
"name": "Demacia",
"nameRef": "Demacia"
},
{
"description": "A champion levels up once this condition is met, even in hand or deck.",
"name": "Level Up",
"nameRef": "LevelUp"
},
{
"description": "",
"name": "Bandle City",
"nameRef": "BandleCity"
},
{
"description": "Can be played whenever you may act. Happens after your opponent has a chance to react.",
"name": "Fast",
"nameRef": "Fast"
},
{
"description": " ",
"name": "Bilgewater",
"nameRef": "Bilgewater"
},
{
"description": "",
"name": "Runeterra",
"nameRef": "Runeterra"
},
{
"description": "Return a unit to hand and remove all effects applied to it.",
"name": "Recall",
"nameRef": "Recall"
},
{
"description": "Lowest Power, with ties broken by lowest Health then lowest Cost",
"name": "Weakest",
"nameRef": "Weakest"
},
{
"description": "Attacking with a support unit will buff the unit to its right.",
"name": "Support",
"nameRef": "Support"
},
{
"description": "Can be played outside of combat when no spells or skills are pending. Happens after your opponent has a chance to react.",
"name": "Slow",
"nameRef": "Slow"
},
{
"description": "Completely removed from the game. Doesn't cause Last Breath and can't be revived.",
"name": "Obliterate",
"nameRef": "Obliterate"
},
{
"description": "These abilities trigger when you resolve a spell.",
"name": "Imbue",
"nameRef": "Imbue"
},
{
"description": " ",
"name": "Targon",
"nameRef": "MtTargon"
},
{
"description": " ",
"name": "Shadow Isles",
"nameRef": "ShadowIsles"
},
{
"description": "Missing Translation",
"name": "Missing Translation",
"nameRef": "AuraVisualFakeKeyword"
},
{
"description": " ",
"name": "Ionia",
"nameRef": "Ionia"
},
{
"description": "Bonus if this is NOT the first card you play in a round.",
"name": "Nightfall",
"nameRef": "Nightfall"
},
{
"description": " ",
"name": "Piltover & Zaun",
"nameRef": "PiltoverZaun"
},
{
"description": " ",
"name": "Freljord",
"nameRef": "Freljord"
},
{
"description": "When I'm summoned, refill 1 spell mana.",
"name": "Attune",
"nameRef": "Attune"
},
{
"description": "Bonus if this is the FIRST card you play in a round.",
"name": "Daybreak",
"nameRef": "Daybreak"
},
{
"description": "Missing Translation",
"name": "Missing Translation",
"nameRef": "SilenceIndividualKeyword"
},
{
"description": "A unit's spell-like effect that allows enemy reactions.",
"name": "Skill",
"nameRef": "Skill"
},
{
"description": "A card triggers its plunder ability when played if you damaged the enemy Nexus this round.",
"name": "Plunder",
"nameRef": "Plunder"
},
{
"description": "While attacking, it strikes both before AND at the same time as its blocker.",
"name": "Double Attack",
"nameRef": "DoubleStrike"
},
{
"description": "The enemy can challenge this unit, forcing it to block.",
"name": "Vulnerable",
"nameRef": "Vulnerable"
},
{
"description": "Can only be blocked by an Elusive unit.",
"name": "Elusive",
"nameRef": "Elusive"
},
{
"description": "Remove a unit from combat. It can't attack or block for the rest of the round.",
"name": "Stun",
"nameRef": "Stun"
},
{
"description": "Each round, the first time an allied card targets me, grant me +1|+1.",
"name": "Fated",
"nameRef": "Fated"
},
{
"description": "Missing Translation",
"name": "Can block Elusives",
"nameRef": "BlockElusive"
},
{
"description": "When I kill a unit, grant me +1|+1.",
"name": "Fury",
"nameRef": "Fury"
},
{
"description": "Negates the next damage the unit would take. Lasts one round.",
"name": "Barrier",
"nameRef": "Barrier"
},
{
"description": "Can't attack or block.",
"name": "Immobile",
"nameRef": "Immobile"
},
{
"description": "After I die, for the rest of the game when allies attack, hallow your first attacker giving it +1|+0 that round",
"name": "Hallowed",
"nameRef": "Hallowed"
},
{
"description": "I have +2|+2 once you've given or summoned allies with 6+ other positive keywords this game.",
"name": "Evolve",
"nameRef": "Evolve"
},
{
"description": "Set a unit's Power to 0 this round. It can be changed after.",
"name": "Frostbite",
"nameRef": "Frostbite"
},
{
"description": "Excess damage I deal to my blocker is dealt to the enemy Nexus.",
"name": "Overwhelm",
"nameRef": "Overwhelm"
},
{
"description": "While attacking, strikes before its blocker.",
"name": "Quick Attack",
"nameRef": "QuickStrike"
},
{
"description": "Takes 1 less damage from all sources.",
"name": "Tough",
"nameRef": "Tough"
},
{
"description": "Heals fully at the end of each round.",
"name": "Regeneration",
"nameRef": "Regeneration"
},
{
"description": "Removes all text and keywords from a unit.",
"name": "Silenced",
"nameRef": "Silenced"
},
{
"description": "Negates the next enemy spell or skill that would affect me.",
"name": "SpellShield",
"nameRef": "SpellShield"
},
{
"description": "Damage this unit deals heals its Nexus that amount.",
"name": "Lifesteal",
"nameRef": "Lifesteal"
},
{
"description": "When you play a created card, grant me +1|+0.",
"name": "Augment",
"nameRef": "Augment"
},
{
"description": "When this strikes while attacking, it deals 1 to the enemy Nexus. This keyword can stack.",
"name": "Impact",
"nameRef": "Impact"
},
{
"description": "The first time only Scout units attack each round, ready your attack.",
"name": "Scout",
"nameRef": "Scout"
},
{
"description": "This unit dies when it strikes or when the round ends.",
"name": "Ephemeral",
"nameRef": "Ephemeral"
},
{
"description": "When you attack while I'm on top of your deck, I Lurk, granting Lurker allies everywhere +1|+0. Max once per round.",
"name": "Lurk",
"nameRef": "Lurker"
},
{
"description": "I strike with my Health instead of my Power.",
"name": "Formidable",
"nameRef": "Formidable"
},
{
"description": "Can choose which enemy unit blocks.",
"name": "Challenger",
"nameRef": "Challenger"
},
{
"description": "Can only be blocked by enemies with 3 or more Power.",
"name": "Fearsome",
"nameRef": "Fearsome"
},
{
"description": " ",
"name": "Can't Block",
"nameRef": "CantBlock"
},
{
"description": "",
"name": "Deep",
"nameRef": "Deep"
}
],
"regions": [
{
"abbreviation": "NX",
"iconAbsolutePath": "http://dd.b.pvp.net/3_11_0/core/en_us/img/regions/icon-noxus.png",
"name": "Noxus",
"nameRef": "Noxus"
},
{
"abbreviation": "DE",
"iconAbsolutePath": "http://dd.b.pvp.net/3_11_0/core/en_us/img/regions/icon-demacia.png",
"name": "Demacia",
"nameRef": "Demacia"
},
{
"abbreviation": "Jhin",
"iconAbsolutePath": "http://dd.b.pvp.net/3_11_0/core/en_us/img/regions/icon-jhin.png",
"name": "Jhin",
"nameRef": "Jhin"
},
{
"abbreviation": "Evelynn",
"iconAbsolutePath": "http://dd.b.pvp.net/3_11_0/core/en_us/img/regions/icon-evelynn.png",
"name": "Evelynn",
"nameRef": "Evelynn"
},
{
"abbreviation": "Bard",
"iconAbsolutePath": "http://dd.b.pvp.net/3_11_0/core/en_us/img/regions/icon-bard.png",
"name": "Bard",
"nameRef": "Bard"
},
{
"abbreviation": "RU",
"iconAbsolutePath": "http://dd.b.pvp.net/3_11_0/core/en_us/img/regions/icon-runeterra.png",
"name": "Runeterra",
"nameRef": "Runeterra"
},
{
"abbreviation": "FR",
"iconAbsolutePath": "http://dd.b.pvp.net/3_11_0/core/en_us/img/regions/icon-freljord.png",
"name": "Freljord",
"nameRef": "Freljord"
},
{
"abbreviation": "SI",
"iconAbsolutePath": "http://dd.b.pvp.net/3_11_0/core/en_us/img/regions/icon-shadowisles.png",
"name": "Shadow Isles",
"nameRef": "ShadowIsles"
},
{
"abbreviation": "MT",
"iconAbsolutePath": "http://dd.b.pvp.net/3_11_0/core/en_us/img/regions/icon-targon.png",
"name": "Targon",
"nameRef": "Targon"
},
{
"abbreviation": "IO",
"iconAbsolutePath": "http://dd.b.pvp.net/3_11_0/core/en_us/img/regions/icon-ionia.png",
"name": "Ionia",
"nameRef": "Ionia"
},
{
"abbreviation": "SH",
"iconAbsolutePath": "http://dd.b.pvp.net/3_11_0/core/en_us/img/regions/icon-shurima.png",
"name": "Shurima",
"nameRef": "Shurima"
},
{
"abbreviation": "BW",
"iconAbsolutePath": "http://dd.b.pvp.net/3_11_0/core/en_us/img/regions/icon-bilgewater.png",
"name": "Bilgewater",
"nameRef": "Bilgewater"
},
{
"abbreviation": "PZ",
"iconAbsolutePath": "http://dd.b.pvp.net/3_11_0/core/en_us/img/regions/icon-piltoverzaun.png",
"name": "Piltover & Zaun",
"nameRef": "PiltoverZaun"
},
{
"abbreviation": "BC",
"iconAbsolutePath": "http://dd.b.pvp.net/3_11_0/core/en_us/img/regions/icon-bandlecity.png",
"name": "Bandle City",
"nameRef": "BandleCity"
}
],
"spellSpeeds": [
{
"name": "Slow",
"nameRef": "Slow"
},
{
"name": "Burst",
"nameRef": "Burst"
},
{
"name": "Fast",
"nameRef": "Fast"
}
],
"rarities": [
{
"name": "COMMON",
"nameRef": "Common"
},
{
"name": "RARE",
"nameRef": "Rare"
},
{
"name": "EPIC",
"nameRef": "Epic"
},
{
"name": "Champion",
"nameRef": "Champion"
},
{
"name": "None",
"nameRef": "None"
}
],
"sets": [
{
"iconAbsolutePath": "http://dd.b.pvp.net/3_11_0/core/en_us/img/sets/set3_crispmip.png",
"name": "Call of the Mountain",
"nameRef": "Set3"
},
{
"iconAbsolutePath": "http://dd.b.pvp.net/3_11_0/core/en_us/img/sets/set5_crispmip.png",
"name": "Beyond the Bandlewood",
"nameRef": "Set5"
},
{
"iconAbsolutePath": "http://dd.b.pvp.net/3_11_0/core/en_us/img/sets/set1_crispmip.png",
"name": "Foundations",
"nameRef": "Set1"
},
{
"iconAbsolutePath": "http://dd.b.pvp.net/3_11_0/core/en_us/img/sets/set2_crispmip.png",
"name": "Rising Tides",
"nameRef": "Set2"
},
{
"iconAbsolutePath": "http://dd.b.pvp.net/3_11_0/core/en_us/img/sets/set4_crispmip.png",
"name": "Empires of the Ascended",
"nameRef": "Set4"
},
{
"iconAbsolutePath": "http://dd.b.pvp.net/3_11_0/core/en_us/img/sets/set6ab_crispmip.png",
"name": "Worldwalker",
"nameRef": "Set6"
},
{
"iconAbsolutePath": "http://dd.b.pvp.net/3_11_0/core/en_us/img/sets/setevent_crispmip.png",
"name": "Events",
"nameRef": "SetEvent"
}
]
}

View file

@ -0,0 +1,5 @@
{
"locales": [
"en_us"
]
}

View file

@ -0,0 +1 @@
Copyright Riot Games, Inc. 2019

40
data/set1-en_us/README.md Normal file
View file

@ -0,0 +1,40 @@
metadata.json
{
"locales": ["{string}", ...],
"clientHash": "{string}"
"gameplayDataHash": "{string}",
"timestamp": "{YYYYMMDDhhmm}",
"patchlineRef": "{string}"
}
cards.json
[
{
"id": "{cardCode}",
"idComponents":
{
"set": "setNumber",
"region":
{
"id": "{shortRegionCode}",
"name": "{regionName}"
}
}
"name": "{name}",
"type": "{type}",
"subType": "{subType}",
"superType": "{superType}",
"description": "{description}",
"keywords": [],
"associatedCards": [{cardCode}, ...]
"health": "{health}",
"attack": "{attack}",
"cost": "{cost}",
"assets":
{
"gameAbsolutePath": "http://{cdn}/{bundleName}/set1/en_us/img/card/game/{cardCode}.png"
}
},
{...}
]

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,5 @@
{
"locales": [
"en_us"
]
}

View file

@ -0,0 +1 @@
Copyright Riot Games, Inc. 2019

40
data/set2-en_us/README.md Normal file
View file

@ -0,0 +1,40 @@
metadata.json
{
"locales": ["{string}", ...],
"clientHash": "{string}"
"gameplayDataHash": "{string}",
"timestamp": "{YYYYMMDDhhmm}",
"patchlineRef": "{string}"
}
cards.json
[
{
"id": "{cardCode}",
"idComponents":
{
"set": "setNumber",
"region":
{
"id": "{shortRegionCode}",
"name": "{regionName}"
}
}
"name": "{name}",
"type": "{type}",
"subType": "{subType}",
"superType": "{superType}",
"description": "{description}",
"keywords": [],
"associatedCards": [{cardCode}, ...]
"health": "{health}",
"attack": "{attack}",
"cost": "{cost}",
"assets":
{
"gameAbsolutePath": "http://{cdn}/{bundleName}/set1/en_us/img/card/game/{cardCode}.png"
}
},
{...}
]

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,5 @@
{
"locales": [
"en_us"
]
}

View file

@ -0,0 +1 @@
Copyright Riot Games, Inc. 2019

40
data/set3-en_us/README.md Normal file
View file

@ -0,0 +1,40 @@
metadata.json
{
"locales": ["{string}", ...],
"clientHash": "{string}"
"gameplayDataHash": "{string}",
"timestamp": "{YYYYMMDDhhmm}",
"patchlineRef": "{string}"
}
cards.json
[
{
"id": "{cardCode}",
"idComponents":
{
"set": "setNumber",
"region":
{
"id": "{shortRegionCode}",
"name": "{regionName}"
}
}
"name": "{name}",
"type": "{type}",
"subType": "{subType}",
"superType": "{superType}",
"description": "{description}",
"keywords": [],
"associatedCards": [{cardCode}, ...]
"health": "{health}",
"attack": "{attack}",
"cost": "{cost}",
"assets":
{
"gameAbsolutePath": "http://{cdn}/{bundleName}/set1/en_us/img/card/game/{cardCode}.png"
}
},
{...}
]

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,5 @@
{
"locales": [
"en_us"
]
}

View file

@ -0,0 +1 @@
Copyright Riot Games, Inc. 2019

40
data/set4-en_us/README.md Normal file
View file

@ -0,0 +1,40 @@
metadata.json
{
"locales": ["{string}", ...],
"clientHash": "{string}"
"gameplayDataHash": "{string}",
"timestamp": "{YYYYMMDDhhmm}",
"patchlineRef": "{string}"
}
cards.json
[
{
"id": "{cardCode}",
"idComponents":
{
"set": "setNumber",
"region":
{
"id": "{shortRegionCode}",
"name": "{regionName}"
}
}
"name": "{name}",
"type": "{type}",
"subType": "{subType}",
"superType": "{superType}",
"description": "{description}",
"keywords": [],
"associatedCards": [{cardCode}, ...]
"health": "{health}",
"attack": "{attack}",
"cost": "{cost}",
"assets":
{
"gameAbsolutePath": "http://{cdn}/{bundleName}/set1/en_us/img/card/game/{cardCode}.png"
}
},
{...}
]

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,5 @@
{
"locales": [
"en_us"
]
}

View file

@ -0,0 +1 @@
Copyright Riot Games, Inc. 2019

40
data/set5-en_us/README.md Normal file
View file

@ -0,0 +1,40 @@
metadata.json
{
"locales": ["{string}", ...],
"clientHash": "{string}"
"gameplayDataHash": "{string}",
"timestamp": "{YYYYMMDDhhmm}",
"patchlineRef": "{string}"
}
cards.json
[
{
"id": "{cardCode}",
"idComponents":
{
"set": "setNumber",
"region":
{
"id": "{shortRegionCode}",
"name": "{regionName}"
}
}
"name": "{name}",
"type": "{type}",
"subType": "{subType}",
"superType": "{superType}",
"description": "{description}",
"keywords": [],
"associatedCards": [{cardCode}, ...]
"health": "{health}",
"attack": "{attack}",
"cost": "{cost}",
"assets":
{
"gameAbsolutePath": "http://{cdn}/{bundleName}/set1/en_us/img/card/game/{cardCode}.png"
}
},
{...}
]

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,5 @@
{
"locales": [
"en_us"
]
}

View file

@ -0,0 +1 @@
Copyright Riot Games, Inc. 2019

40
data/set6-en_us/README.md Normal file
View file

@ -0,0 +1,40 @@
metadata.json
{
"locales": ["{string}", ...],
"clientHash": "{string}"
"gameplayDataHash": "{string}",
"timestamp": "{YYYYMMDDhhmm}",
"patchlineRef": "{string}"
}
cards.json
[
{
"id": "{cardCode}",
"idComponents":
{
"set": "setNumber",
"region":
{
"id": "{shortRegionCode}",
"name": "{regionName}"
}
}
"name": "{name}",
"type": "{type}",
"subType": "{subType}",
"superType": "{superType}",
"description": "{description}",
"keywords": [],
"associatedCards": [{cardCode}, ...]
"health": "{health}",
"attack": "{attack}",
"cost": "{cost}",
"assets":
{
"gameAbsolutePath": "http://{cdn}/{bundleName}/set1/en_us/img/card/game/{cardCode}.png"
}
},
{...}
]

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,5 @@
{
"locales": [
"en_us"
]
}

View file

@ -61,7 +61,7 @@ pub struct Card {
/// The subtypes the card has, such as `PORO`.
pub subtypes: Vec<String>,
/// The [CardSupertype] the card belongs to, such as `Champion`.
pub supertype: CardSupertype,
pub supertype: String,
/// If `true`, the card can be found in chests, crafted, or used in decks.
/// If `false`, the card is not available for direct use, as it is probably created by another card.
@ -104,17 +104,6 @@ pub enum CardType {
}
/// Possible card supertypes.
#[non_exhaustive]
#[derive(serde::Serialize, serde::Deserialize, Clone, Debug)]
pub enum CardSupertype {
#[serde(alias = "")]
None,
Champion,
}
/// Possible card rarities.
#[non_exhaustive]
#[derive(serde::Serialize, serde::Deserialize, Clone, Debug)]

View file

@ -1,13 +1,11 @@
#[macro_use] extern crate tantivy;
use teloxide::prelude::*;
use teloxide::types::*;
use log::*;
use reqwest::Url;
use itertools::Itertools;
mod data;
mod search;
mod telegram;
/// Run the bot.
@ -60,30 +58,7 @@ async fn main() {
async move {
let reply = results.iter()
/*
.map(|card| InlineQueryResult::Photo(InlineQueryResultPhoto {
id: card.card_code.to_owned(),
title: Some(card.name.to_owned()),
description: Some(card.description_raw.to_owned()),
caption: Some(card.description_raw.to_owned()),
photo_url: Url::parse( & card.assets.get(0).expect("card to have assets").game_absolute_path).expect("card to have a valid asset URL"),
thumb_url: Url::parse( & card.assets.get(0).expect("card to have assets").full_absolute_path).expect("card to have a valid asset URL"),
photo_width: None,
photo_height: None,
parse_mode: None,
caption_entities: None,
reply_markup: None,
input_message_content: None,
}))
*/
.map(|card| InlineQueryResult::Article(InlineQueryResultArticle::new(
card.card_code.to_owned(),
card.name.to_owned(),
InputMessageContent::Text(InputMessageContentText::new(
format!("<b>{}<b>\n\n{}", &card.name, &card.description_raw)
))
)))
.collect_vec();
.map(telegram::result::create_inlinequeryresult);
if let Err(e) = bot.answer_inline_query(&query.id, reply).send().await {
error!("{:?}", e);

134
src/telegram/format.rs Normal file
View file

@ -0,0 +1,134 @@
use itertools::Itertools;
use crate::data::schema::{Card, CardType};
pub fn format_card(card: &Card) -> String {
match card.card_type {
CardType::Spell => format!(
"{}{}{}{}\n{}\n{}",
format_name(&card.name),
format_types(&card.supertype, &card.subtypes),
format_keywords(&card.keywords),
format_mana(card.cost),
format_description(&card.description_raw, &card.levelup_description_raw),
format_flavor(&card.assets.get(0).expect("card to have at least one asset").full_absolute_path, &card.flavor_text),
),
CardType::Unit => format!(
"{}{}{}{}{}\n{}\n{}",
format_name(&card.name),
format_types(&card.supertype, &card.subtypes),
format_keywords(&card.keywords),
format_mana(card.cost),
format_stats(card.attack, card.health),
format_description(&card.description_raw, &card.levelup_description_raw),
format_flavor(&card.assets.get(0).expect("card to have at least one asset").full_absolute_path, &card.flavor_text),
),
CardType::Ability => format!(
"{}{}{}\n{}\n{}",
format_name(&card.name),
format_types(&card.supertype, &card.subtypes),
format_keywords(&card.keywords),
format_description(&card.description_raw, &card.levelup_description_raw),
format_flavor(&card.assets.get(0).expect("card to have at least one asset").full_absolute_path, &card.flavor_text),
),
CardType::Landmark => format!(
"{}{}{}{}\n{}\n{}",
format_name(&card.name),
format_types(&card.supertype, &card.subtypes),
format_keywords(&card.keywords),
format_mana(card.cost),
format_description(&card.description_raw, &card.levelup_description_raw),
format_flavor(&card.assets.get(0).expect("card to have at least one asset").full_absolute_path, &card.flavor_text),
),
CardType::Trap => format!(
"{}{}{}\n{}\n{}",
format_name(&card.name),
format_types(&card.supertype, &card.subtypes),
format_keywords(&card.keywords),
format_description(&card.description_raw, &card.levelup_description_raw),
format_flavor(&card.assets.get(0).expect("card to have at least one asset").full_absolute_path, &card.flavor_text),
),
}
}
fn escape(s: &str) -> String {
s
.replace("&", "&amp;")
.replace("<", "&lt;")
.replace(">", "&gt;")
}
fn format_name(name: &String) -> String {
format!("<b><u>{}</u></b>\n", escape(&name))
}
fn format_types(supertype: &String, subtypes: &Vec<String>) -> String {
let mut types = vec![];
if supertype != "" {
types.push(supertype.to_owned())
}
let mut source = subtypes.to_owned();
types.append(&mut source);
let mut types = types.iter()
.map(|t| escape(&t))
.map(|k| k.to_lowercase());
let typestring = types.join(", ");
if typestring == "" {
return String::from("")
}
else {
return format!("<i>{}</i>\n", &typestring)
}
}
fn format_mana(cost: i8) -> String {
format!("{} mana\n", cost)
}
fn format_stats(attack: i8, health: i8) -> String {
format!("{}|{}\n", attack, health)
}
fn format_keywords(keywords: &Vec<String>) -> String {
if keywords.len() == 0 {
return String::from("")
}
else {
format!(
"{}\n",
keywords.iter()
.map(|k| escape(&k))
.map(|k| k.to_lowercase())
.map(|k| format!("[{}]", &k))
.join(" ")
)
}
}
fn format_description(desc: &String, levelup: &String) -> String {
if levelup == "" {
if desc == "" {
String::from("")
}
else {
format!("{}\n", escape(&desc))
}
}
else {
format!("{}\n\n<u>Level up</u>: {}\n", escape(&desc), escape(&levelup))
}
}
fn format_flavor(full_art: &String, flavor: &String) -> String {
format!(r#"<a href="{}"><i>{}</i></a>"#, &full_art, escape(&flavor))
}

2
src/telegram/mod.rs Normal file
View file

@ -0,0 +1,2 @@
pub mod format;
pub mod result;

25
src/telegram/result.rs Normal file
View file

@ -0,0 +1,25 @@
use crate::data::schema::Card;
use teloxide::types::*;
use reqwest::Url;
use crate::telegram::format::format_card;
pub fn create_inlinequeryresult(card: &Card) -> InlineQueryResult {
InlineQueryResult::Photo(InlineQueryResultPhoto {
id: card.card_code.to_owned(),
title: Some(card.name.to_owned()),
description: Some(card.description_raw.to_owned()),
caption: Some(format_card(&card)),
photo_url: Url::parse(
&card.assets.get(0).expect("card to have assets").game_absolute_path).expect("card to have a valid asset URL"
),
thumb_url: Url::parse(
&card.assets.get(0).expect("card to have assets").game_absolute_path).expect("card to have a valid asset URL"
),
photo_width: Some(680),
photo_height: Some(1024),
parse_mode: Some(ParseMode::Html),
caption_entities: None,
reply_markup: None,
input_message_content: None,
})
}