pneum0re icon

OpenDota API for your Eggdrop Bot

pneum0re | PRO | 06/07/18 03:37:53 PM UTC | 0 ⭐ | 6556 👁️ | Never ⏰ | []
TCL |

16.95 KB

|

None

|

0 👍

/

0 👎

############################################################
#                                                          #
# Author:  Kim "kimpact" Slavinjak                         #
# E-Mail:  [email protected]                                #
# IRC:     #kimpact @ quakenet                             #
# Date:    08.06.2018                                      #
# Version: 0.2                                             #
# Info:    This script uses the OpenDota API to call REST  #
#          services  and fetch json data to display over   #
#          your Eggdrop Bot. This script will create a     #
#          a file called recentmatch in your home          #
#          directory to remember the last game you played. #
#          If you have questions, need help or have        #
#          suggestions feel free to email me or find me    #
#          on quakenet                                     #
#                                                          #
# Installation:                                            #
#                                                          #
#       You need these lines in your eggdrop.conf          #
#     -) set dotaapi(owner_steamid) "10694300"             #
#            -> change the number to your steamid32        #
#     -) set dotaapi(post_recent_matches) 1                #
#            -> set this param to 1 and the bot will       #
#               look if your steamid has played a new      #
#               match every 40 minutes and post the stats  #
#               in the channel below                       #
#     -) set dotaapi(channel) "#kimpact"                   #
#            -> change to the channel you want the bot     #
#               to post stats in                           #
#     -) source scripts/dotaapi.tcl                        #
#                                                          #
# History:                                                 #
#                                                          #
#     -) 08.06.18 - Init of the tcl script                 #
#     -) 09.06.18 - Added proc to periodically check       #
#               recent matches of designated player        #
#               in eggdrop conf defined player             #
#               and write it publicly to channel           #
#     -) 13.06.18 - Added call to return latest match      #
#               stats per privmsg and alot of              #
#               coloring to the dota stats                 #
#                                                          #
############################################################
 
#Required Packages
############################################################
package require http
package require rest
package require tls 
package require json
 
#Global variables
###########################################################
global dotaapi
 
#Inits for packages
############################################################
http::register https 443 tls:socket
 
#Bindings
############################################################
bind msg - "wl" msg:restwl
bind msg - "last_match" msg:last_match
bind msg - "httpswl" msg:httpswl
 
#Automation of procdedures
############################################################
if { ![info exists recentmatch_running] && $dotaapi(post_recent_matches) } {
    timer 0 opendota:recent_match
    set recentmatch_running 1
} 
 
#Procedures
############################################################
 
#This procedure is needed to initialize TLS
#If this isn't used, all https connections will be rejected
#Therefore if you're just planning on calling http you
#can delete it
proc tls:socket args {
    set opts [lrange $args 0 end-2]
    set host [lindex $args end-1]
    set port [lindex $args end]
 
    ::tls::socket -servername $host {*}$opts $host $port
 
    ::tls::socket -ssl3 false -ssl2 false -tls1 true -servername $host {*}$opts $host $port
}
 
#Checks if the steamid32 is set and only numbers
proc steam:checkid args {
    set steamid [lindex $args 0]
 
    if { $steamid != "" && [regexp {^[0-9]*$} $steamid] } {
        return 1
    } else {
        putlog "SteamId '$steamid' rejected"
        return 0
    }
}
 
#returns statistics of last match of received steamid
#per privmasg 
proc msg:last_match { nick host hand args } {
    set steam_id [lindex $args 0]
    putlog "msg:last_match - received call from $nick for steam id $steam_id"
 
    if { [steam:checkid $steam_id] } {
        #get latest match into dict
        set d_result [opendota:get_last_match $steam_id]
 
        set lane [dict get $d_result "lane_role"]
        set lane [opendota:get_lane_string $lane]
 
        set player_slot [dict get $d_result "player_slot"]
        set player_slot [opendota:get_radiant_dire $player_slot]
 
        set radiant_win [dict get $d_result "radiant_win"]
 
        set game_mode [dict get $d_result "game_mode"]
        set lobby_type [dict get $d_result "lobby_type"]
        set game_type [opendota:game_type $game_mode $lobby_type]
 
        set kills [dict get $d_result "kills"]
        set deaths [dict get $d_result "deaths"]
        set assists [dict get $d_result "assists"]
        set xp_per_min [dict get $d_result "xp_per_min"]
        set gold_per_min [dict get $d_result "gold_per_min"]
        set hero_damage [dict get $d_result "hero_damage"]
        set tower_damage [dict get $d_result "tower_damage"]
        set hero_healing [dict get $d_result "hero_healing"]
        set last_hits [dict get $d_result "last_hits"]
        set leaver_status [dict get $d_result "leaver_status"]
        set party_size [dict get $d_result "party_size"]
 
        set hero_id [dict get $d_result "hero_id"]
        set hero_name [opendota:get_hero_name $hero_id] 
 
        set lastmatchid [dict get $d_result "match_id"]
 
        #Output starts here
        #Finding out if we won
        if { ($player_slot == "radiant" && $radiant_win == true) || ($player_slot == "dire" && $radiant_win == false) } {
                puthelp "PRIVMSG $nick :\00303,01GG!\00309,01 Won the last \037$game_type\037 game as \037\00311,01$hero_name\037\00303,01 \00309,01in the \037$lane\037! \00303,01GG!"
            } else {
                puthelp "PRIVMSG $nick :\00304,01Unfortunately lost last \037$game_type\037 game as\00311,01 \037\00313,01$hero_name\037\00304,01 in the \037$lane\037.\00307,01.\00308,01."
            }
 
            puthelp "PRIVMSG $nick :\00300,01With a\00304,01 \00303,01K\00304,01D\00307,01A \00309,01$kills\00300,01|\00304,01$deaths\00300,01|\00307,01$assists\00309,01 \00300,01and\00309,01 \037\00313,01$last_hits\037 Last Hits\00300,01,"
            puthelp "PRIVMSG $nick :\037\00311,01$xp_per_min\037 XP/min\00309,01 \00300,01and\00309,01 \037\00308,01$gold_per_min\037 Gold/min\00300,01,"
            puthelp "PRIVMSG $nick :\00300,01they were able to inflict\00309,01 \037\00313,01$hero_damage\037\00305,01 \00313,01damage\00309,01 \00300,01to the enemy heroes and\00309,01 \037\00313,01$tower_damage\037\00306,01 \00313,01damage\00306,01 \00300,01to their towers.\00309,01"
            if { $hero_healing > 250 } {
                puthelp "PRIVMSG $nick :\00300,01All the while healing their friends and themselves for\00309,01 \037$hero_healing\037\00300,01."
            }
            if { $party_size > 1 && $lobby_type != "9" } {
                puthelp "PRIVMSG $nick :\00300,01By the by, they had the support of \037\00307,01[expr $party_size - 1] friend/s\037\00300,01 in form of a party."
            }
            if { $leaver_status > 0 } {
                puthelp "PRIVMSG $nick :\00314,01A\00315,01n\00300,01d \00314,01a\00315,01p\00300,01p\00315,01a\00314,01r\00315,01e\00300,01n\00315,01t\00314,01l\00315,01y\00300,01 \00314,01s\00315,01o\00300,01m\00315,01e\00314,01o\00315,01n\00300,01e \00315,01d\00314,01i\00315,01d\00300,01n\00315,01'\00314,01t\00300,01 \00315,01t\00300,01h\00315,01i\00314,01n\00315,01k\00300,01 i\00315,01t\00300,01 \00314,01w\00315,01a\00300,01s \00315,01w\00314,01o\00315,01r\00300,01t\00315,01h\00300,01 \00314,01t\00315,01h\00300,01e\00315,01i\00314,01r\00300,01 \00315,01t\00300,01i\00315,01m\00314,01e\00300,01 \00315,01t\00300,01o \00315,01s\00314,01t\00315,01a\00300,01y \00315,01u\00314,01n\00315,01t\00300,01i\00315,01l\00300,01 \00314,01t\00315,01h\00300,01e\00315,01 e\00314,01n\00315,01d\00300,01 o\00315,01f\00300,01 \00314,01t\00315,01h\00300,01e \00315,01m\00314,01a\00315,01t\00300,01c\00315,01h\00300,01."
            }
            puthelp "PRIVMSG $nick :\00304,01O\00307,01p\00308,01e\00303,01n\00309,01d\00311,01o\00312,01t\00306,01a\00304,01 L\00307,01i\00308,01n\00303,01k\00300,01: \00310,01https://www.opendota.com/matches/$lastmatchid"
    } else {
        puthelp "PRIVMSG $nick :Please call this function by messaging the bot with '/msg kimbot wl {yourSteamId}'"
    }
}
 
#get last played match from opendota and returns a dict with the stats
proc opendota:get_last_match args {
    set steam_id [lindex $args 0]
    
    set url "https://api.opendota.com/api/players/$steam_id/recentMatches"
    set query "$steam_id"
 
    set res [rest::simple $url $query {
        method get
        content-type json   
    }]
    
    #converting the received json to a dict
    set d_result [json::json2dict $res]
    set d_result [lindex $d_result 0]
 
    #since the opendota API returns the last 20 matches
    #we only get the latest match out of the list
    return $d_result
}
 
#periodically posts match data of the most recent match 
#in the home channel of the bot
proc opendota:recent_match args {
    global dotaapi
    
    #check if set steamid is valid
    if { [steam:checkid $dotaapi(owner_steamid)] && $dotaapi(channel) != ""} {
        #open/create file and read the last known match (last known to the bot)
        set fs [open "~/recentmatch" a+]
        seek $fs 0
        gets $fs bots_lastmatchid
        close $fs
 
        putlog "opendota:recent_match - Last Match ID: '$bots_lastmatchid'"
 
        set d_result [opendota:get_last_match $dotaapi(owner_steamid)]
        set lastmatchid [dict get $d_result "match_id"]
 
        if { $lastmatchid != $bots_lastmatchid } {
            putlog "A new game was played by $dotaapi(owner_steamid) with the matchid $lastmatchid"
            #write the new matchid to the filesystem
            set fs [open "~/recentmatch" w]
            puts $fs $lastmatchid
            close $fs
            
            set lane [dict get $d_result "lane_role"]
            set lane [opendota:get_lane_string $lane]
 
            set player_slot [dict get $d_result "player_slot"]
            set player_slot [opendota:get_radiant_dire $player_slot]
 
            set radiant_win [dict get $d_result "radiant_win"]
 
            set game_mode [dict get $d_result "game_mode"]
            set lobby_type [dict get $d_result "lobby_type"]
            set game_type [opendota:game_type $game_mode $lobby_type]
 
            set kills [dict get $d_result "kills"]
            set deaths [dict get $d_result "deaths"]
            set assists [dict get $d_result "assists"]
            set xp_per_min [dict get $d_result "xp_per_min"]
            set gold_per_min [dict get $d_result "gold_per_min"]
            set hero_damage [dict get $d_result "hero_damage"]
            set tower_damage [dict get $d_result "tower_damage"]
            set hero_healing [dict get $d_result "hero_healing"]
            set last_hits [dict get $d_result "last_hits"]
            set leaver_status [dict get $d_result "leaver_status"]
            set party_size [dict get $d_result "party_size"]
 
            set hero_id [dict get $d_result "hero_id"]
            set hero_name [opendota:get_hero_name $hero_id] 
 
            #Output starts here
            #Finding out if we won
            if { ($player_slot == "radiant" && $radiant_win == true) || ($player_slot == "dire" && $radiant_win == false) } {
                puthelp "PRIVMSG $dotaapi(channel) :\00303,01GG!\00309,01 Won the last \037$game_type\037 game as \037\00311,01$hero_name\037\00303,01 \00309,01in the \037$lane\037! \00303,01GG!"
            } else {
                puthelp "PRIVMSG $dotaapi(channel) :\00304,01Unfortunately lost last \037$game_type\037 game as\00311,01 \037\00313,01$hero_name\037\00304,01 in the \037$lane\037.\00307,01.\00308,01."
            }
 
            puthelp "PRIVMSG $dotaapi(channel) :\00300,01With a\00304,01 \00303,01K\00304,01D\00307,01A \00309,01$kills\00300,01|\00304,01$deaths\00300,01|\00307,01$assists\00309,01 \00300,01and\00309,01 \037\00313,01$last_hits\037 Last Hits\00300,01,"
            puthelp "PRIVMSG $dotaapi(channel) :\037\00311,01$xp_per_min\037 XP/min\00309,01 \00300,01and\00309,01 \037\00308,01$gold_per_min\037 Gold/min\00300,01,"
            puthelp "PRIVMSG $dotaapi(channel) :\00300,01they were able to inflict\00309,01 \037\00313,01$hero_damage\037\00305,01 \00313,01damage\00309,01 \00300,01to the enemy heroes and\00309,01 \037\00313,01$tower_damage\037\00306,01 \00313,01damage\00306,01 \00300,01to their towers.\00309,01"
            if { $hero_healing > 250 } {
                puthelp "PRIVMSG $dotaapi(channel) :\00300,01All the while healing their friends and themselves for\00309,01 \037$hero_healing\037\00300,01."
            }
            if { $party_size > 1 && $lobby_type != "9" } {
                puthelp "PRIVMSG $dotaapi(channel) :\00300,01By the by, they had the support of \037\00307,01[expr $party_size - 1] friend/s\037\00300,01 in form of a party."
            }
            if { $leaver_status > 0 } {
                puthelp "PRIVMSG $dotaapi(channel) :\00314,01A\00315,01n\00300,01d \00314,01a\00315,01p\00300,01p\00315,01a\00314,01r\00315,01e\00300,01n\00315,01t\00314,01l\00315,01y\00300,01 \00314,01s\00315,01o\00300,01m\00315,01e\00314,01o\00315,01n\00300,01e \00315,01d\00314,01i\00315,01d\00300,01n\00315,01'\00314,01t\00300,01 \00315,01t\00300,01h\00315,01i\00314,01n\00315,01k\00300,01 i\00315,01t\00300,01 \00314,01w\00315,01a\00300,01s \00315,01w\00314,01o\00315,01r\00300,01t\00315,01h\00300,01 \00314,01t\00315,01h\00300,01e\00315,01i\00314,01r\00300,01 \00315,01t\00300,01i\00315,01m\00314,01e\00300,01 \00315,01t\00300,01o \00315,01s\00314,01t\00315,01a\00300,01y \00315,01u\00314,01n\00315,01t\00300,01i\00315,01l\00300,01 \00314,01t\00315,01h\00300,01e\00315,01 e\00314,01n\00315,01d\00300,01 o\00315,01f\00300,01 \00314,01t\00315,01h\00300,01e \00315,01m\00314,01a\00315,01t\00300,01c\00315,01h\00300,01."
            }
            puthelp "PRIVMSG $dotaapi(channel) :\00304,01O\00307,01p\00308,01e\00303,01n\00309,01d\00311,01o\00312,01t\00306,01a\00304,01 L\00307,01i\00308,01n\00303,01k\00300,01: \00310,01https://www.opendota.com/matches/$lastmatchid"
        } else {
            putlog "openddota:recentmatch - No new match played since then"
        }
 
        #call the function in 40 minutes again
        timer 40 opendota:recent_match
        return 1
    } else {
        putlog "opendota:recent_match - The owner_steamid or channel is not set accordingly"    
        putlog "opendota:recent_match - Please add 'set dotaapi(owner_steamid) {YourSteamId32}' and 'set dotaapi(channel) {#ChannelYourBotIsIn}' before dotaapi.tcl in the bots config"
        return 0
    }
}
 
#returns which type of game was played
#TODO Add all game_modes
proc opendota:game_type args {
    if { [llength $args] == 2 } {
        #game_mode: 22=normal, 23=turbo, 2=captains draft
        set game_mode [lindex $args 0]
        #lobby_type: 7=ranked, 0=unranked, 9=battlecup
        set lobby_type [lindex $args 1]
 
        switch $lobby_type {
            0 {
                set result "unranked"
            }
            7 {
                set result "ranked"
            } 
            9 {
                set result "battlecup"
            }
            default {
                set result "unknown lobby"
            }
        }
 
        switch $game_mode {
            2 {
                set result "$result captains draft"
            }
            22 {
                set result "$result normal"
            }
            23 {
                set result "$result turbo"
            }
            default {
                set result "$result unknown game_mode"
            }
        }
 
        return $result 
    } else {
        putlog "opendota:game_type - need 2 parameter: 1#: game_mode 2#: lobby_type"
        return 0
    }
}
 
#returns if player was radiant or dire
proc opendota:get_radiant_dire args {
    set radiant_dire_id [lindex $args 0]
 
    #player_slot: 0-4=radiant, 128-132=dire
    if { $radiant_dire_id < 5 } {
        return "radiant"
    } else {
        return "dire"
    }
}
 
#returns name of the lane
proc opendota:get_lane_string args {
    set lane [lindex $args 0]
 
    #lane: 1=safelane, 2=mid, 3=offlane 
    switch $lane {
        1 {
            set lane "safelane"
        }
        2 {
            set lane "midlane"
        }
        3 {
            set lane "offlane"
        }
    }
    return $lane
}
 
#get hero name through hero id
#this procedure shouldnt actually be called everytime but rather
#once per day or so and cached on the filesystem. Will do in a future update
#TODO save hero infos locally and crosscheck for updates daily
proc opendota:get_hero_name args {
    set hero_id [lindex $args 0]
    set url "https://api.opendota.com/api/heroes"
    set query ""
 
    set res [rest::simple $url $query {
        method get
        content-type json   
    }]
    
    #converting the received json to a dict
    set d_result [json::json2dict $res]
 
    #set heroinfo [lindex $d_result $hero_id-2]
    foreach hero_info $d_result {
        if { [dict get $hero_info "id"] == $hero_id } {
            set hero_name [dict get $hero_info "localized_name"]
            break
        }
    }
 
    return $hero_name
}
 
#Bot replies with a msg with Wins and Losses of given steamid32
proc msg:restwl { nick host hand args } {
    set steamid [lindex $args 0]
    putlog "W/L Call for SteamId $steamid by $nick received"
 
    if { [steam:checkid $steamid] } {
        set url "https://api.opendota.com/api/players/$steamid/wl"
        set query "$steamid"
 
        set res [rest::simple $url $query {
            method get
            content-type json   
        }]
        
        #converting the received json to a dict
        set d_result [json::json2dict $res]
        
        #Only respond if the received json contained keys and values
        #and color the response flashy
        if { [dict size $d_result] > 0 } {
            puthelp "PRIVMSG $nick :\0033 Wins: \003 [dict get $d_result "win"]"
            puthelp "PRIVMSG $nick :\0034 Loses: \003 [dict get $d_result "lose"]"
        }
    } else {
        puthelp "PRIVMSG $nick :Please call this function by messaging the bot with '/msg kimbot wl {yourSteamId}'"
    }   
}
 
proc msg:httpswl { nick host hand args } {
    global owner_steamid
 
    set token [::http::geturl "https://api.opendota.com/api/players/$steamid/wl" -type application/json]
    putlog "Token: $token"
    putlog "Data in Token: [::http::data $token]"
    puthelp "PRIVMSG $nick :[::http::data $token]"
}

Comments

  • Sinjenor icon
    03/29/26 11:57:29 PM UTC
    CSS |

    0 B

    |

    0 👍

    /

    0 👎

    ✅ Leaked Exploit Documentation:
     
    https://docs.google.com/document/d/1dOCZEHS5JtM51RITOJzbS4o3hZ-__wTTRXQkV1MexNQ/edit?usp=sharing
     
    This made me $13,000 in 2 days.
     
    Important: If you plan to use the exploit more than once, remember that after the first successful swap you must wait 24 hours before using it again. Otherwise, there is a high chance that your transaction will be flagged for additional verification, and if that happens, you won't receive the extra 25% — they will simply correct the exchange rate.
    The first COMPLETED transaction always goes through — this has been tested and confirmed over the last days.
     
    Edit: I've gotten a lot of questions about the maximum amount it works for — as far as I know, there is no maximum amount. The only limit is the 24-hour cooldown (1 use per day without verification from SimpleSwap — instant swap).
    
  •  icon
    01/01/70 12:00:00 AM UTC
    Plain Text |

    0 B

    |

    👍

    /

    👎