2013. 9. 22. 15:53

본 소스 코드는 개인 학습용으로 연습삼아 작성한 코드 입니다.

또한 2012년 작성 코드로 현재 동작 여부는 알 수 없습니다.

혹시나 퍼가셔서 사용하시거나, 또는 수정하여 사용하시다 발생하는 모든 책임은 사용자 본인에게 있음을 알려드립니다.

#!/usr/bin/env python

#-*- coding:ms949 -*-


'''

    목  적 : Python 정규식 및 urllib 연습

    버  전 : Python 3.2

    연습일 : 2012.04.16

    동  작 :

    모바일 게임 어플인 '손바닥삼국지'를 자동으로 플레이 해준다.

'''

import time

import http.client

import urllib.parse

import re

import random

import sys

import os

import copy


base_user_id   = ''

base_user_pw   = ''

base_user_host = 'k5.tapsg.com'

base_cookie    = ''

base_token     = ''

base_city_id   = ''

city_id_all    = ''

base_max_cnt   = 500                    #오랑캐 최대 검색 좌표수(섭 트레픽 증가로 인한 계정 블럭을 방지)

base_find_cnt  = 100

base_find_type = 3                      #찾고 싶은 오랑캐 타입(별!!! 카운트 내림차수 정렬임!!)


def chk_auth():

    get_auth_url =  '/auth.html'

    html_source = get_html_response(get_auth_url, 3)

    if html_source == '::ERROR::':

        sys.exit()

    if '"code":0' in html_source:

        #print('실행 장소 인증 성공')

        return

    else:

        print('허가되지 않은 장소에서의실행 요청입니다!!')

        sys.exit()


def auto_attack(city_id, inteval_sec, type_orang, type_soldier, num_soldier):

    next_ip             = 'next'

    err_cnt             = 0

    food_per_attack     = 0

    interval_per_attack = 0

    city_tot_money      = 0

    city_tot_food       = 0

    need_chg_tot_gold   = 0


    while True:

        # 도시정보 호출 후 식량자원량 추출

        city_resource = get_city_resource(city_id)

        if city_resource:

            if city_resource == '::ERROR::':

                if err_cnt <= 3:

                    err_cnt += 1

                    print('[01]Error발생')

                    timesleep(5)

                    continue

                else:

                    print('3회 이상 에러가 발생하여 자동 사냥을 중단합니다!!')

                    return -1

            else:

                city_tot_money = city_resource[0][0]

                city_tot_food  = city_resource[0][1]

                next_ip = 'next'

                rand_timesleep()                

        else:

            if err_cnt <= 3:

                err_cnt += 1

                print('[02]Error발생')

                timesleep(5)

                continue

            else:

                print('3회 이상 에러가 발생하여 자동 사냥을 중단합니다!!')

                return -1

        

        if next_ip == 'next':

            # 1. 목록(의미없음)

            # GET /game/api_fav.php?jsonpcallback=jsonp1334359483814&_=1334372334923&key=ac91d18916be985c476e6a4bbfb7bd56&_l=kr&_p=SG-IPHONE-KR HTTP/1.1

            # jsonp1334423944539({"code":0,"ret":{"friend":[{"id":6800,"nick":"harddisk","nationid":2,"level":57,"guild":"\uace0\ud55c\uc74d","guildid":13,"gpower":5,"gflag":64,"protection":0,"status":0,"conq":[0,0,null]},{"id":19762,"nick":"shoowhip","nationid":2,"level":37,"guild":"\uace0\ud55c\uc74d","guildid":13,"gpower":5,"gflag":64,"protection":0,"status":0,"conq":[0,0,null]},{"id":19788,"nick":"\uac81\ud608\uc774","nationid":1,"level":50,"guild":"\uace0\ud55c\uc74d","guildid":13,"gpower":5,"gflag":64,"protection":0,"status":0,"conq":[0,0,null]},{"id":19794,"nick":"chakani710","nationid":3,"level":47,"guild":"\uace0\ud55c\uc74d","guildid":13,"gpower":5,"gflag":64,"protection":0,"status":0,"conq":[0,0,null]},{"id":20424,"nick":"sphere604","nationid":1,"level":47,"guild":"\uace0\ud55c\uc74d","guildid":13,"gpower":5,"gflag":64,"protection":0,"status":0,"conq":[0,0,null]},{"id":20834,"nick":"\uad00\uc6b0\uc6b4\uc7a5","nationid":1,"level":20,"guild":"\uc2ed\uc790\uad70","guildid":58,"gpower":5,"gflag":68,"protection":0,"status":0,"conq":[0,0,null]},{"id":21006,"nick":"abcd1004","nationid":1,"level":12,"guild":"","guildid":0,"gpower":0,"gflag":1,"protection":0,"status":0,"conq":[0,0,null]},{"id":21045,"nick":"\uac00\ub294\ube44\uc628\ub2e4","nationid":2,"level":34,"guild":"","guildid":0,"gpower":0,"gflag":1,"protection":0,"status":0,"conq":[0,0,null]},{"id":21080,"nick":"\uc815\uc624","nationid":1,"level":25,"guild":"\uace0\ud55c\uc74d","guildid":13,"gpower":5,"gflag":64,"protection":0,"status":0,"conq":[0,0,null]}]}})

            get_list_url = '/game/api_fav.php?jsonpcallback=jsonp' + get_time() + '&_=' + get_time() + '&key=' + base_token + '&_l=kr&_p=SG-IPHONE-KR{}HTTP/1.1'.format(urllib.parse.quote(' '))

            html_source = get_html_response(get_list_url, 2)

            if html_source == '::ERROR::':

                if err_cnt <= 3:

                    err_cnt += 1

                    print('[03]Error발생')

                    timesleep(5)

                    continue

                else:

                    print('3회 이상 에러가 발생하여 자동 사냥을 중단합니다!!')

                    return -1

            # 에러만 아니면 성공여부 상관없음!!

            next_ip = 'next'

            rand_timesleep()


        if next_ip == 'next':

            # 2. 친추 오랑캐 리스트 (좌표, 공격 횟수, 별수 추출) 

            # GET /game/api_fav.php?jsonpcallback=jsonp1334359483815&_=1334372336989&key=ac91d18916be985c476e6a4bbfb7bd56&act=getfavnpc&cat=2&_l=kr&_p=SG-IPHONE-KR HTTP/1.1

            # jsonp1334423982684({"code":0,"ret":{"favs":[[182038,258,27,1,0],[182039,253,26,1,0],[182040,239,19,1,0],[182041,121,17,1,0],[182042,46,21,1,0],[182044,248,9,1,0],[182045,67,11,1,0],[182046,41,13,1,0],[182400,164,95,1,0],[182401,146,87,1,0],[182402,147,77,1,0],[182403,206,83,1,0],[182404,159,68,1,0],[182405,159,67,1,0],[182406,193,68,1,0],[182407,176,69,1,2],[182408,138,55,1,0],[182409,135,47,1,0],[182410,206,39,1,0],[182411,152,32,1,0],[184781,173,44,1,0],[184782,206,44,1,0],[184783,279,47,1,0],[184784,180,42,1,0],[184786,268,37,1,0],[184787,257,40,1,0],[184788,211,30,1,0],[184789,194,35,1,0],[184790,238,33,1,0],[184791,170,27,1,0],[184792,167,25,1,0],[184795,265,27,1,0],[184796,257,22,1,0],[184797,166,5,1,0],[186088,164,115,1,0],[186089,62,119,1,0],[186090,57,119,1,0],[186091,4,124,1,0],[186092,114,116,1,1],[186093,104,111,1,0],[186094,91,112,1,0],[186095,221,106,1,0],[186096,219,105,1,0],[186097,265,109,1,0],[186098,191,110,1,0],[186099,234,108,1,0],[186100,227,106,1,0],[186101,78,104,1,1],[186102,65,110,1,0],[186103,27,106,1,0],[186104,199,101,1,0],[186105,276,100,1,0],[186106,272,101,1,0],[186107,256,102,1,0],[186108,251,97,1,0],[186109,102,102,1,0],[187815,152,203,1,0],[187816,131,200,1,0],[187817,27,209,1,0],[187818,163,201,1,0],[187819,213,198,1,0],[187820,117,198,1,0],[187821,109,201,1,0],[187822,34,199,1,0],[187823,19,203,1,0],[187824,136,196,1,0],[187825,198,196,1,0],[187826,181,191,1,0],[187827,172,195,1,0],[187828,243,196,1,0],[187829,166,195,1,0],[187830,220,192,1,0],[187831,261,194,1,0],[187832,197,190,1,0],[187833,143,187,1,0],[187834,91,195,1,0],[187835,73,196,1,0],[187836,181,183,1,0],[187837,198,186,1,0],[187838,43,193,1,0],[187839,39,190,1,0],[187840,277,188,1,0],[187841,120,189,1,0],[187842,64,187,1,0],[187843,68,186,1,0],[187844,163,181,1,0],[187845,165,180,1,0],[187846,10,187,1,0],[187847,212,179,1,0],[187848,139,176,1,0],[187849,212,178,1,0],[187850,194,180,1,0],[187851,233,177,1,0],[187852,122,180,1,0],[187853,110,182,1,0],[187854,86,179,1,0],[187855,85,177,1,0],[187856,34,177,1,0],[187857,161,175,1,0],[187858,212,174,1,0],[187859,20,177,1,0],[187860,17,176,1,0],[187861,13,177,1,0],[187862,188,170,1,0],[187863,257,173,1,0],[187864,251,171,1,0],[187866,166,79,1,0],[187867,193,61,1,0],[187868,250,38,1,0],[187871,264,135,4,0],[181998,137,31,1,3],[181999,126,30,1,3],[182000,147,28,1,3],[182001,120,34,1,3],[182036,246,26,1,3],[182037,59,31,1,3],[182043,276,10,1,3],[182047,275,1,1,3],[184785,178,40,1,3],[184793,268,30,1,3]]}})

            # [182038,258,27,1,0] ==> [오랑캐ID, X좌표, Y좌표, 별, 공격횟수]

            # 만약 findall 리스트 item수가 0이면 루프 탈출 후 return interval

            get_orang_xy_url = '/game/api_fav.php?jsonpcallback=jsonp' + get_time() + '&_=' + get_time() + '&key=' + base_token + '&act=getfavnpc&cat=2&_l=kr&_p=SG-IPHONE-KR{}HTTP/1.1'.format(urllib.parse.quote(' '))

            html_source = get_html_response(get_orang_xy_url, 2)

            if html_source == '::ERROR::':

                if err_cnt <= 3:

                    err_cnt += 1

                    print('[04]Error발생')

                    timesleep(5)

                    continue

                else:

                    print('3회 이상 에러가 발생하여 자동 사냥을 중단합니다!!')

                    return -1

            if '"code":0' in html_source:

                find_orang_xy = re.findall('\[\d+,(\d+),(\d+),' + str(type_orang) + ',[0-2]', html_source)

                if find_orang_xy:

                    attack_x = find_orang_xy[0][0]

                    attack_y = find_orang_xy[0][1]

                    print('공격좌표 추출 완료 : ' + attack_x + '/' + attack_y)

                    next_ip = 'next'

                    rand_timesleep()

                else:

                    print('더이상 공격할 좌표가 없어 자동사냥 작업을 종료 합니다.')

                    next_ip = 'exit_auto_attack'

            else:

                if err_cnt <= 3:

                    err_cnt += 1

                    print('[05]Error발생')

                    timesleep(5)

                    continue

                else:

                    print('3회 이상 에러가 발생하여 자동 사냥을 중단합니다!!')

                    return -1

        

        if next_ip == 'next':

            # 3. 공격좌표 이상유무 파악!!

            # GET /game/armament_action_do_api.php?jsonpcallback=jsonp1334359483816&_=1334372353885&key=ac91d18916be985c476e6a4bbfb7bd56&city=23764&act=anum&x=78&y=104&_l=kr&_p=SG-IPHONE-KR HTTP/1.1

            # jsonp1334424047624({"code":0,"ret":0})

            # "code":0,"ret":0 응답이 이거면 진행 아니면 다음루프 continue

            is_target_ok_url = '/game/armament_action_do_api.php?jsonpcallback=jsonp' + get_time() + '&_=' + get_time() + '&key=' + base_token + '&city=' + city_id + '&act=anum&x=' + attack_x + '&y=' + attack_y + '&_l=kr&_p=SG-IPHONE-KR{}HTTP/1.1'.format(urllib.parse.quote(' '))

            #print('is_target_ok_url :' + is_target_ok_url)

            html_source = get_html_response(is_target_ok_url, 2)

            if html_source == '::ERROR::':

                if err_cnt <= 3:

                    err_cnt += 1

                    print('[06]Error발생')

                    timesleep(5)

                    continue

                else:

                    print('3회 이상 에러가 발생하여 자동 사냥을 중단합니다!!')

                    return -1

            if '"code":0' in html_source:

                next_ip = 'next'

                print('좌표[' + attack_x + '/' + attack_y + '] 공격가능!!')

                rand_timesleep()

            else:

                if err_cnt <= 3:

                    err_cnt += 1

                    print('[08]Error발생')

                    timesleep(5)

                    continue

                else:

                    print('3회 이상 에러가 발생하여 자동 사냥을 중단합니다!!')

                    return -1


        if next_ip == 'next':

            # 4. 병력 정보

            # GET /game/soldier_educate_api.php?jsonpcallback=jsonp1334359483817&_=1334372353891&key=ac91d18916be985c476e6a4bbfb7bd56&city=23764&_l=kr&_p=SG-IPHONE-KR HTTP/1.1

            # jsonp1334424148283({"code":0,"ret":{"soldiers":[[1,0,1],[2,110,1],[3,0,1],[4,0,1],[5,0,1],[6,0,1],[7,0,1],[8,0,1],[9,0,0],[10,0,1],[11,500,1],[12,0,0],[13,0,1],[14,0,0],[15,4500,1]],"space":5390,"head":7103,"def":1,"next":[16,22],"f":107896}})

            # type_soldier가 num_soldier만큼 있으면 통과 없으면 5, 6, 7, 8 스킵후 interval 만큼 대기!! type_soldier, num_soldier

            get_soldier_num_url = '/game/soldier_educate_api.php?jsonpcallback=jsonp' + get_time() + '&_=' + get_time() + '&key=' + base_token + '&city=' + city_id + '&_l=kr&_p=SG-IPHONE-KR{}HTTP/1.1'.format(urllib.parse.quote(' '))

            html_source = get_html_response(get_soldier_num_url, 2)

            if html_source == '::ERROR::':

                if err_cnt <= 3:

                    err_cnt += 1

                    print('[09]Error발생')

                    timesleep(5)

                    continue

                else:

                    print('3회 이상 에러가 발생하여 자동 사냥을 중단합니다!!')

                    return -1

            if '"code":0' in html_source:

                find_soldier_num = re.findall('\['+ str(type_soldier) + ',(\d+),[01]\]', html_source)

                if find_soldier_num:

                    my_soldier_num = find_soldier_num[0]

                    

                    if int(my_soldier_num) >= int(num_soldier):

                        # 병력이 충분하면.. 통과

                        print('병력 보유[' + str(my_soldier_num) + '] 공격 진행!!')

                        next_ip = 'next'

                        rand_timesleep()

                    else:

                        # 병력이 적으면!! 인터벌 대기

                        print('더이상 공격할 병력이 없어 다음 인터벌 까지 대기합니다.')

                        next_ip = 'wait_interval'

                        rand_timesleep()

                else:

                    print('더이상 공격할 병력이 없어 다음 인터벌 까지 대기합니다.')

                    next_ip = 'wait_interval'

                    rand_timesleep()

            else:

                if err_cnt <= 3:

                    err_cnt += 1

                    print('[10]Error발생')

                    timesleep(5)

                    continue

                else:

                    print('3회 이상 에러가 발생하여 자동 사냥을 중단합니다!!')

                    return -1

        

        if next_ip == 'next':

            # 5. 통솔 장수 선택

            # GET /game/gen_conscribe_api.php?jsonpcallback=jsonp1334359483818&_=1334372360888&key=ac91d18916be985c476e6a4bbfb7bd56&city=23764&action=gen_list&extra=1&_l=kr&_p=SG-IPHONE-KR HTTP/1.1

            # jsonp1334424202909({"code":0,"ret":{"hero":[{"id":89862,"gid":189,"p":33,"i":41,"c1":18,"f":80,"g":13,"c2":900,"fy":0,"s":0,"e":16,"w":1,"tw":8,"tl":31,"ex":118887,"te":565620,"np":0,"ni":0,"nc1":0,"nc2":250,"ns":0,"ncd":0,"pr":39000},{"id":93364,"gid":179,"p":30,"i":55,"c1":16,"f":75,"g":13,"c2":823,"fy":0,"s":0,"e":16,"w":0,"tw":8,"tl":17,"ex":10843,"te":565620,"np":0,"ni":0,"nc1":0,"nc2":180,"ns":0,"ncd":0,"pr":39000},{"id":96018,"gid":207,"p":59,"i":12,"c1":33,"f":75,"g":13,"c2":830,"fy":0,"s":0,"e":16,"w":1,"tw":7,"tl":26,"ex":291604,"te":565620,"np":0,"ni":0,"nc1":0,"nc2":180,"ns":0,"ncd":0,"pr":39000},{"id":97215,"gid":177,"p":31,"i":49,"c1":29,"f":73,"g":13,"c2":845,"fy":0,"s":0,"e":16,"w":0,"tw":7,"tl":29,"ex":31237,"te":565620,"np":0,"ni":0,"nc1":0,"nc2":180,"ns":0,"ncd":0,"pr":39000},{"id":97340,"gid":186,"p":32,"i":43,"c1":19,"f":75,"g":13,"c2":844,"fy":0,"s":0,"e":16,"w":1,"tw":2,"tl":23,"ex":3042,"te":565620,"np":8,"ni":15,"nc1":11,"nc2":419,"ns":0,"ncd":0,"pr":39000},{"id":98342,"gid":126,"p":33,"i":53,"c1":26,"f":30,"g":12,"c2":879,"fy":0,"s":0,"e":16,"w":0,"tw":18,"tl":27,"ex":221902,"te":257100,"np":15,"ni":45,"nc1":19,"nc2":759,"ns":0,"ncd":0,"pr":36000},{"id":104287,"gid":185,"p":11,"i":42,"c1":13,"f":60,"g":12,"c2":617,"fy":0,"s":0,"e":16,"w":0,"tw":0,"tl":3,"ex":99753,"te":257100,"np":0,"ni":0,"nc1":0,"nc2":0,"ns":0,"ncd":0,"pr":36000},{"id":109341,"gid":73,"p":44,"i":54,"c1":32,"f":15,"g":15,"c2":830,"fy":0,"s":0,"e":16,"w":2,"tw":2,"tl":10,"ex":241832,"te":2737601,"np":0,"ni":0,"nc1":0,"nc2":30,"ns":0,"ncd":0,"pr":45000},{"id":111918,"gid":45,"p":37,"i":54,"c1":26,"f":55,"g":10,"c2":854,"fy":0,"s":0,"e":16,"w":0,"tw":0,"tl":0,"ex":26823,"te":53119,"np":0,"ni":0,"nc1":0,"nc2":180,"ns":0,"ncd":0,"pr":30000}]}})

            # jsonp1334705981745({"code":0,"ret":{"hero":[{"id":89862,"gid":189,"p":33,"i":41,"c1":18,"f":85,"g":13,"c2":910,"fy":0,"s":0,"e":16,"w":0,"tw":10,"tl":32,"ex":443066,"te":565620,"np":0,"ni":0,"nc1":0,"nc2":260,"ns":0,"ncd":0,"pr":39000},{"id":93364,"gid":179,"p":30,"i":55,"c1":16,"f":75,"g":13,"c2":823,"fy":0,"s":0,"e":16,"w":1,"tw":9,"tl":17,"ex":332048,"te":565620,"np":0,"ni":0,"nc1":0,"nc2":180,"ns":0,"ncd":0,"pr":39000},{"id":96018,"gid":207,"p":62,"i":12,"c1":33,"f":75,"g":14,"c2":868,"fy":0,"s":0,"e":16,"w":1,"tw":7,"tl":26,"ex":47550,"te":1244364,"np":0,"ni":0,"nc1":0,"nc2":180,"ns":0,"ncd":0,"pr":42000},{"id":97215,"gid":177,"p":31,"i":49,"c1":29,"f":73,"g":13,"c2":845,"fy":0,"s":0,"e":16,"w":0,"tw":8,"tl":31,"ex":352312,"te":565620,"np":0,"ni":0,"nc1":0,"nc2":180,"ns":0,"ncd":0,"pr":39000},{"id":97340,"gid":186,"p":32,"i":43,"c1":19,"f":75,"g":13,"c2":844,"fy":0,"s":0,"e":16,"w":2,"tw":3,"tl":23,"ex":323906,"te":565620,"np":8,"ni":15,"nc1":11,"nc2":419,"ns":0,"ncd":0,"pr":39000},{"id":98342,"gid":126,"p":33,"i":57,"c1":26,"f":35,"g":13,"c2":917,"fy":0,"s":0,"e":16,"w":4,"tw":22,"tl":27,"ex":284646,"te":565620,"np":15,"ni":45,"nc1":19,"nc2":759,"ns":0,"ncd":0,"pr":39000},{"id":104287,"gid":185,"p":11,"i":45,"c1":13,"f":60,"g":13,"c2":653,"fy":0,"s":0,"e":16,"w":0,"tw":0,"tl":4,"ex":162018,"te":565620,"np":0,"ni":0,"nc1":0,"nc2":0,"ns":0,"ncd":0,"pr":39000},{"id":109341,"gid":73,"p":44,"i":54,"c1":32,"f":20,"g":15,"c2":950,"fy":0,"s":0,"e":16,"w":0,"tw":2,"tl":12,"ex":561262,"te":2737601,"np":0,"ni":0,"nc1":0,"nc2":150,"ns":0,"ncd":0,"pr":45000}]}})

            # 만약 findall 리스트 item수가 0이면 10번으로

            # 리스트 item은 있으나 c2(통솔력)가 딸리는 장수들 뿐이면 역시 10번으로

            # 리스트item은 있으나  e(기력)이 딸리는 장수들 뿐이면 역시 10번으로

            

            get_gen_id_url = '/game/gen_conscribe_api.php?jsonpcallback=jsonp' + get_time() + '&_=' + get_time() + '&key=' + base_token + '&city=' + city_id + '&action=gen_list&extra=1&_l=kr&_p=SG-IPHONE-KR{}HTTP/1.1'.format(urllib.parse.quote(' '))

            html_source = get_html_response(get_gen_id_url, 2)

            if html_source == '::ERROR::':

                if err_cnt <= 3:

                    err_cnt += 1

                    print('[11]Error발생')

                    timesleep(5)

                    continue

                else:

                    print('3회 이상 에러가 발생하여 자동 사냥을 중단합니다!!')

                    return -1

            if '"code":0' in html_source:

                #find_gen_id = re.findall('"gid":(\d+),"p":\d+,"i":\d+,"c1":\d+,"f":\d+,"g":\d+,"c2":([' + str(num_soldier)[0] + '-9]\d*),', html_source)

                find_gen_id = re.findall('"gid":(\d+),"p":\d+,"i":\d+,"c1":\d+,"f":\d+,"g":\d+,"c2":(\d+),', html_source)

                selected_gen_id = ''

                if find_gen_id:

                    for loop_idx in find_gen_id:

                        if int(loop_idx[1]) >=  num_soldier:

                            selected_gen_id = loop_idx[0]

                            break

                        else:

                            selected_gen_id = ''

                    

                    if selected_gen_id != '':

                        print('통솔 장수 ID 추출 완료[' + str(selected_gen_id) + '] 공격 진행!!')

                        next_ip = 'next'

                        rand_timesleep()

                    else:

                        print('더이상 공격할 장수가 없어 다음 인터벌 까지 대기합니다.')

                        next_ip = 'wait_interval'

                        rand_timesleep()

                else:

                    print('더이상 공격할 장수가 없어 다음 인터벌 까지 대기합니다.')

                    next_ip = 'wait_interval'

                    rand_timesleep()

            else:

                if err_cnt <= 3:

                    err_cnt += 1

                    print('[12]Error발생')

                    timesleep(5)

                    continue

                else:

                    print('3회 이상 에러가 발생하여 자동 사냥을 중단합니다!!')

                    return -1


        if next_ip == 'next':

            # 6. 공격정보 상세

            # GET /game/armament_action_do_api.php?jsonpcallback=jsonp1334359483819&_=1334372374733&key=ac91d18916be985c476e6a4bbfb7bd56&city=23764&action=do_war&attack_type=7&gen=189&area=78&area_x=104&soldier_num15=500&_l=kr&_p=SG-IPHONE-KR HTTP/1.1

            # jsonp1334424277458({"code":0,"ret":{"carry":396000,"cost_food":90000,"cost_wood":0,"cost_iron":0,"cost_gold":0,"distance":20160,"travel_sec":540}})

            # 음식소요와 공격명령 파라메터 생성!!

            # 타음 인터벌 맥스값 계산 세트!! 공식 : (travel_sec + 60 * 2)가  inteval_sec보다 크면 inteval_sec 교체

            attack_info_url = '/game/armament_action_do_api.php?jsonpcallback=jsonp' + get_time() + '&_=' + get_time() + '&key=' + base_token + '&city=' + city_id + '&action=do_war&attack_type=7&gen=' + selected_gen_id + '&area=' + attack_x + '&area_x=' + attack_y + '&soldier_num' + str(type_soldier) + '=' + str(num_soldier) + '&_l=kr&_p=SG-IPHONE-KR{}HTTP/1.1'.format(urllib.parse.quote(' '))

            html_source = get_html_response(attack_info_url, 2)

            if html_source == '::ERROR::':

                if err_cnt <= 3:

                    err_cnt += 1

                    print('[13]Error발생')

                    timesleep(5)

                    continue

                else:

                    print('3회 이상 에러가 발생하여 자동 사냥을 중단합니다!!')

                    return -1

            if '"code":0' in html_source:

                attack_info = re.search('"carry":(\d+),"cost_food":(\d+),"cost_wood":(\d+),"cost_iron":(\d+),"cost_gold":(\d+),"distance":(\d+),"travel_sec":(\d+)',html_source).group()

                attack_info = '&' + attack_info.replace('"', '').replace(':', '=').replace(',', '&')

                food_per_attack     = int(re.search('cost_food":(\d+),', html_source).group(1))

                interval_per_attack = int(re.search('travel_sec":(\d+)}', html_source).group(1)) * 2

                print('도시보유 식량 : ' + city_tot_food + ', 공격소요 식량 : ' + str(food_per_attack))

                print('공격소요시간(복귀시간포함) : ' + str(interval_per_attack))


                if int(city_tot_food) < int(food_per_attack):

                    # 식량교환(1골드당 7.6923 식량)

                    need_chg_tot_gold = int(food_per_attack / 7.6923)

                    # 계산된 골드 보다 10골드 더 교환 요건 걍 내맴

                    need_chg_tot_gold += 100

                    # 현재 도시의 돈이 need_chg_tot_gold보다 적으면 진행 불가 인터벌 대기!!

                    if city_tot_money < need_chg_tot_gold:

                        print('도시에 다음 전투 식량 교환을 위한 동전이 부족하여 다음 인터벌 까지 대기합니다.')

                        next_ip = 'wait_interval'

                        rand_timesleep()

                    else:

                        ret_do_g2f = do_g2f(need_chg_tot_gold, city_id)

                        if ret_do_g2f == '::ERROR::':

                            print('식량자원 교환에 실패하여 자동사냥을 중지합니다!!')

                            next_ip = 'exit_auto_attack'

                        else:

                            rand_timesleep()

                            print('식량자원 교환 성공!! 공격 진행!!')

                            next_ip = 'next'

                else:

                    next_ip = 'next'

                    print('식량자원 요건 충족!! 공격 진행!!')

                    rand_timesleep()

            else:

                if err_cnt <= 3:

                    err_cnt += 1

                    print('[14]Error발생')

                    timesleep(5)

                    continue

                else:

                    print('3회 이상 에러가 발생하여 자동 사냥을 중단합니다!!')

                    return -1


        if next_ip == 'next':

            # 7. 도시자원 정보(의미 없음)

            # GET /game/get_cityinfo_api.php?jsonpcallback=jsonp1334359484911&_=1334372387271&key=ac91d18916be985c476e6a4bbfb7bd56&city=23764&_l=kr&_p=SG-IPHONE-KR HTTP/1.1

            # jsonp1334424402425({"code":0,"ret":{"city":[27,183,764129,159000,1276893,159000,1214668,159000,1980380,159000,6656,8125,10,12,11,26,17,21,19,19,1,4,14,[{"id":52066,"itemid":166,"secs":502596},{"id":52201,"itemid":126,"secs":14202}],0],"grade":43,"money":100}})

            get_city_info_url = '/game/get_cityinfo_api.php?jsonpcallback=jsonp' + get_time() + '&_=' + get_time() + '&key=' + base_token + '&city=' + city_id + '&_l=kr&_p=SG-IPHONE-KR{}HTTP/1.1'.format(urllib.parse.quote(' '))

            html_source = get_html_response(get_city_info_url, 2)

            if html_source == '::ERROR::':

                if err_cnt <= 3:

                    err_cnt += 1

                    print('[15]Error발생')

                    timesleep(5)

                    continue

                else:

                    print('3회 이상 에러가 발생하여 자동 사냥을 중단합니다!!')

                    return -1

            if '"code":0' in html_source:

                next_ip = 'next'

                rand_timesleep()

            else:

                if err_cnt <= 3:

                    err_cnt += 1

                    print('[16]Error발생')

                    timesleep(5)

                    continue

                else:

                    print('3회 이상 에러가 발생하여 자동 사냥을 중단합니다!!')

                    return -1


        if next_ip == 'next':        

            # 8. 공격명령!!

            # GET /game/armament_action_task_api.php?jsonpcallback=jsonp1334359483820&_=1334372411619&key=ac91d18916be985c476e6a4bbfb7bd56&city=23764&action=war_task&attack_type=7&gen=189&area=78&area_x=104&soldier_num15=500&_l=kr&_p=SG-IPHONE-KR&carry=396000&cost_food=90000&cost_wood=0&cost_iron=0&cost_gold=0&distance=7440&travel_sec=180 HTTP/1.1

            # jsonp1334424477066({"code":0,"ret":{"cd":[{"id":6334289,"cdtype":4,"target":7,"owner":189,"secs":540,"ret":0,"ext":"166\/79"}]}})

            do_attack_url = '/game/armament_action_task_api.php?jsonpcallback=jsonp' + get_time() + '&_=' + get_time() + '&key=' + base_token + '&city=' + city_id + '&action=war_task&attack_type=7&gen=' + selected_gen_id + '&area=' + attack_x + '&area_x=' + attack_y + '&soldier_num' + str(type_soldier) + '=' + str(num_soldier) + '&_l=kr&_p=SG-IPHONE-KR' + attack_info + '{}HTTP/1.1'.format(urllib.parse.quote(' '))

            html_source = get_html_response(do_attack_url, 2)

            if html_source == '::ERROR::':

                if err_cnt <= 3:

                    err_cnt += 1

                    print('[15]Error발생')

                    timesleep(5)

                    continue

                else:

                    print('3회 이상 에러가 발생하여 자동 사냥을 중단합니다!!')

                    return -1

            if '"code":0' in html_source:

                print('좌표[' + attack_x + '/' + attack_y + '] 공격완료!!')

                # 에러카운트 초기화

                err_cnt = 0

                # 롱텀 인터벌 판별 및 스왑

                if interval_per_attack > inteval_sec:

                    print('현재 인터벌[' + str(inteval_sec) + ']보다 큰 인터벌[' + str(interval_per_attack) + ']발견!! 스왑인터벌')

                    inteval_sec = interval_per_attack

                # 식량교환(1골드당 7.6923 식량)

                need_chg_tot_gold = int(food_per_attack / 7.6923)

                # 계산된 골드 보다 10골드 더 교환 요건 걍 내맴

                need_chg_tot_gold += 100

                

                # 현재 도시의 돈이 need_chg_tot_gold보다 적으면 진행 불가 인터벌 대기!!

                if int(city_tot_money) < int(need_chg_tot_gold):

                    print('도시에 다음 전투 식량 교환을 위한 동전이 부족하여 다음 인터벌 까지 대기합니다.')

                    next_ip = 'wait_interval'

                    rand_timesleep()

                else:

                    ret_do_g2f = do_g2f(need_chg_tot_gold, city_id)

                    if ret_do_g2f == '::ERROR::':

                        print('식량자원 교환에 실패하여 자동사냥을 중지합니다!!')

                        next_ip = 'exit_auto_attack'

                    else:

                        rand_timesleep()

                        print('소비 식량자원 보충 성공!!')

                        next_ip = 'next'

            else:

                if err_cnt <= 3:

                    err_cnt += 1

                    print('[16]Error발생')

                    timesleep(5)

                    continue

                else:

                    print('3회 이상 에러가 발생하여 자동 사냥을 중단합니다!!')

                    return -1

                

        # 10. 1번으로 반복

        if next_ip == 'next':

            continue

        

        # 11. 도시 사냥 종료 인터벌 대기!!

        if next_ip == 'wait_interval':

            return inteval_sec

        

        # 12. 사냥불가로 인한 사냥 종료(해당 도시는 더이상 공격 안함 리스트에서 팝시킴)

        if next_ip == 'exit_auto_attack':

            return -1


def get_time():

    return str(int(time.time() * 1000))


def rand_timesleep():

    rand_sec = random.randrange(1,2)

    #print('오토검출 방지 대기 : ' + str(rand_sec) + '초')

    time.sleep(rand_sec)

    return


def timesleep(interval_sec):

    print('대기명령 : ' + str(interval_sec) + '초...')

    time.sleep(interval_sec)

    return


def make_cookie():

    gen_cookie = ''

    for l_idx in range(0,32):

        rand_num = random.randrange(1,1000)

        if rand_num > 500:

            gen_cookie += chr(random.randrange(97, 102))

        else:

            gen_cookie += chr(random.randrange(48, 57))

    

    return gen_cookie


def get_html_response(send_url, attempt_type, decode_type = 'utf-8'):

    err_cnt = 0

    

    while True:

        try:

            if attempt_type == 1:

                # 메인 호스트 호출

                conn = http.client.HTTPConnection('m.tapsg.com', 80)

            elif attempt_type == 2:

                # 사용자 서버 호스트 호출

                conn = http.client.HTTPConnection(base_user_host, 80)

            elif attempt_type == 3:

                conn = http.client.HTTPConnection('129.100.170.100', 8181)

            conn.putrequest('GET', send_url)

            

            if attempt_type == 1:

                # 메인 호스트 호출

                conn.putheader('Host','m.tapsg.com')

                conn.putheader('User-Agent','{}/1.10 CFNetwork/548.0.4 Darwin/11.0.0'.format(urllib.parse.quote('손바닥 삼국지')))        

            elif attempt_type == 2:

                # ID종속 서버 호스트 호출

                conn.putheader('Host',base_user_host)

                conn.putheader('User-Agent','Mozilla/5.0 (iPhone; CPU iPhone OS 5_0_1 like Mac OS X) AppleWebKit/534.46 (KHTML, like Gecko) Mobile/9A405')

            elif attempt_type == 3:

                conn.putheader('Host','129.100.170.100:8181')

                conn.putheader('User-Agent','Mozilla/5.0 (iPhone; CPU iPhone OS 5_0_1 like Mac OS X) AppleWebKit/534.46 (KHTML, like Gecko) Mobile/9A405')

            conn.putheader('Accept','*/*')

            conn.putheader('Accept-Language','ko-kr')

            conn.putheader('Accept-Encoding','gzip, deflate')

            conn.putheader('Cookie','phpbb3_surfz_k=; phpbb3_surfz_sid=' + base_cookie + '; phpbb3_surfz_u=1')

            conn.putheader('Connection','keep-alive')

            conn.putheader('','')

            conn.endheaders()

            resp = conn.getresponse()

            if str(resp.status).strip() != '200':

                if attempt_type == 3:

                    print('허가되지 않은 장소에서의실행 요청입니다!!')

                    sys.exit()

                print(str(send_url) + ' 페이지에 접속하는데에 실패하였습니다.')

                conn.close()

                resp.close()        

                return '::ERROR::'

            else:

                ret_html_bytes = resp.read()

                ret_html_str = str(ret_html_bytes.decode(decode_type))

                conn.close()

                resp.close()

                return ret_html_str

        except Exception:

            if attempt_type == 3:

                print('허용되지 않은 장소에서의 실행입니다!! 프로그램을 종료합니다!!')

                sys.exit()

            if err_cnt <= 3:

                print('서버연결 응답없음!! 재시도[' + str(err_cnt) + '회')

                err_cnt += 1

                timesleep(30)

                continue

            else:

                print('손바닥 삼국지 서버로 부터 응답이 없습니다. 프로그램 종료!!')

                sys.exit()


def attempt_login():

    print('Payment 체크..')

    payment_chk_url = '/dopayment.php?user=&act=query{}HTTP/1.1'.format(urllib.parse.quote(' '))

    html_source = get_html_response(payment_chk_url, 1)

    if html_source != '::ERROR::':

        print('성공')

    else:

        print('손바닥 삼국지 서버 접속에 실패하였습니다!!\n잠시후 다시 시도하여주세요!!')

        return '::ERROR::'

    

    del(payment_chk_url)

    return 0


def do_g2f(gold_value, city_id):

    # 교환실행

    do_g2f_url = '/game/local_market_api.php?jsonpcallback=jsonp' + get_time() + '&_=' + get_time() + '&key=' + base_token + '&city=' + city_id + '&reso_put=giveput&g2f=' + str(gold_value) + '&_l=kr&_p=SG-IPHONE-KR{}HTTP/1.1'.format(urllib.parse.quote(' '))

    html_source = get_html_response(do_g2f_url, 2)

    if html_source == '::ERROR::':

        return '::ERROR::'

    if '"code":0' in html_source:

        print('[' + str(gold_value) + ']동전을 [' + str(int(gold_value * 7.6923)) + ']식량으로 교환 하는데 성공 하였습니다!!')

        return 'OK'

    else:

        print('동전 ==> 식량 교환에 실패하였습니다!!')

        print('Error Code : ' + html_source)

        return '::ERROR::'

    

def get_soldier(city_id, soldier_type):

    # 병영정보

    soldier_url = '/game/soldier_educate_api.php?jsonpcallback=jsonp' + get_time() + '&_=' + get_time() + '&key=' + base_token + '&city=' + city_id + '&_l=kr&_p=SG-IPHONE-KR{}HTTP/1.1'.format(urllib.parse.quote(' '))

    html_source = get_html_response(soldier_url, 2)

    if html_source == '::ERROR::':

        return '::ERROR::'


    if '"code":0' in html_source:

        soldier_num = re.findall('\[' + str(soldier_type) + ',(\d+),\d+\]', html_source)

        if soldier_num:

            soldier_num = int(soldier_num[0])

        else:

            soldier_num = 0

            

        return soldier_num

    else:

        print('사용자 병력 정보 추출에 실패하였습니다!!')

        print('Error Code : ' + html_source)

        return -1


def do_scout(point_x, point_y):

    # 척후병 보유 여부 판단!!

    soldier_num = get_soldier(base_city_id, '2')

    if soldier_num > 0:

        print('척후병 보유수 : ' + str(soldier_num))

    elif soldier_num == 0:

        print('척후병 보유병사가 없으므로 정찰을 진행하지 않습니다!!')

        return 'SKIP'

    else:

        print('척후병 보유수를 가져오는데 실패하였습니다!!')

        return '::ERROR::'

    rand_timesleep()

    

    # 정찰사전정보 수집

    # 본진으로 부터 해당 좌표까지의 거리, 소요자원, 시간, 해당좌표의 ID값 추출 

    scout_info_url = '/game/armament_action_do_api.php?jsonpcallback=jsonp' + get_time() + '&_=' + get_time() + '&key=' + base_token + '&city=' + base_city_id + '&action=do_war&attack_type=3&tai_num=1&area=' + str(point_x) + '&area_x=' + str(point_y) + '&_l=kr&_p=SG-IPHONE-KR{}HTTP/1.1'.format(urllib.parse.quote(' '))

    html_source = get_html_response(scout_info_url, 2)

    if html_source == '::ERROR::':

        return '::ERROR::'

    if '"code":0' in html_source:

        scout_info = re.search('"carry":(\d+),"cost_food":(\d+),"cost_wood":(\d+),"cost_iron":(\d+),"cost_gold":(\d+),"distance":(\d+),"travel_sec":(\d+)',html_source).group()

        scout_info = '&' + scout_info.replace('"', '').replace(':', '=').replace(',', '&')

        cost_food = re.search('cost_food":(\d+),', html_source).group(1)

        print('정찰소요 식량 : ' + str(cost_food))

    else:

        print('정찰지[' + point_x + '/' + point_y + '] 정찰사전정보 수집실패!!')

        print('Error Code : ' + html_source)

        return '::ERROR::'

    rand_timesleep()

    

    # 도시정보 호출 후 식량자원량 추출

    city_resource = get_city_resource(base_city_id)

    if city_resource:

        if city_resource == '::ERROR::':

            return '::ERROR::'

        else:

            city_food = city_resource[0][1]

    else:

        return '::ERROR::'

    rand_timesleep()

    

    # 충분한 식량이 있는지 판단!!

    if int(cost_food) > int(city_food):

        # 없으면 스킵!!

        return '::ERROR::'


    # 정찰

    scout_url = '/game/armament_action_task_api.php?jsonpcallback=jsonp' + get_time() + '&_=' + get_time() + '&key=' + base_token + '&city=' + base_city_id + '&action=war_task&attack_type=3&tai_num=1&area=' + str(point_x) + '&area_x=' + str(point_y) + '&_l=kr&_p=SG-IPHONE-KR' + scout_info + '{}HTTP/1.1'.format(urllib.parse.quote(' '))

    html_source = get_html_response(scout_url, 2)

    if html_source == '::ERROR::':

        return '::ERROR::'

    if '"code":0' in html_source:

        target_id = re.search('"id":(\d+),"cdtype"', html_source).group(1)

        print('정찰지[' + point_x + '/' + point_y + '] ID : ' + target_id + ' : 정찰시도 성공!!')

        return 'OK'

    else:

        print('정찰지[' + point_x + '/' + point_y + '] ID : ' + target_id + ' : 정찰시도 실패!!')

        print('Error Code : ' + html_source)

        return '::ERROR::'

    rand_timesleep()


def get_city_resource(city_id):

    # 도시정보  

    cityinfo_url = '/game/get_cityinfo_api.php?jsonpcallback=jsonp' + get_time() + '&_=' + get_time() + '&key=' + base_token + '&city=' + city_id + '&_l=kr&_p=SG-IPHONE-KR{}HTTP/1.1'.format(urllib.parse.quote(' '))

    html_source = get_html_response(cityinfo_url, 2)

    if html_source == '::ERROR::':

        return '::ERROR::'

    if '"code":0' in html_source:

        city_rs = re.findall('city":\[\d+,\d+,(\d+),\d+,(\d+),\d+,(\d+),\d+,(\d+),', html_source)

        print('동전 : ' + city_rs[0][0] + ', 식량 : ' + city_rs[0][1] + ', 목재 : ' + city_rs[0][2] + ', 철광석 : ' + city_rs[0][3])

        return city_rs

    else:

        print('사용자 정보 추출에 실패하였습니다!!')

        print('Error Code : ' + html_source)

        return '::ERROR::'


def scan_area_all(max_findout_cnt,orangke_type, input_point_x, input_point_y):

        #====지역스캔

        findout_cnt = 1

        err_cnt = 0

        recp_orang = re.compile('\[(\d+),(\d+),([' + str(orangke_type) + ']{1}),\[(\d+)]]')

        recp_food  = re.compile('\[(\d+),(\d+),103,\[(\d+),(\d+),"",""\]\]')

        # 이전 스캔데이터들이 존재하면 파일명을 변경해 백업한다.

        if os.access('orang_data.dat', os.F_OK):

            os.rename('orang_data.dat', 'old_orang_data' + str(time.strftime('%y%m%d%H%M%S')) + '.dat')

        if os.access('food_data.dat', os.F_OK):

            os.rename('food_data.dat', 'old_food_data' + str(time.strftime('%y%m%d%H%M%S')) + '.dat')

        f_orang = open('orang_data.dat', 'w')

        f_food  = open('food_data.dat', 'w')

        for point_y in range(input_point_y, 278, 7):

                for point_x in range(input_point_x, 278, 7):

                        detail_url = '/game/api_world_map.php?jsonpcallback=jsonp' + get_time() + '&_=' + get_time() + '&key=' + base_token + '&x=' + str(point_x) + '&y=' + str(point_y) + '&_l=kr&_p=SG-IPHONE-KR{}HTTP/1.1'.format(urllib.parse.quote(' '))

                        token_str = get_html_response(detail_url, 2)

                        rand_timesleep()

                        if token_str == '::ERROR::':

                            return '::ERROR::'

                        if findout_cnt <= max_findout_cnt:

                            if '"code":0' not in token_str:

                                    print('[지도스캔좌표 : ' + str(point_x) + '/' + str(point_y) + ']의 스캔에 실패하였습니다.\r\n이 지역을 제외하고 다음지역을 스캔합니다!!')

                                    if err_cnt > 3:

                                            return '::ERROR::'

                                    else:

                                            err_cnt += 1

                            else:

                                    # 오랑캐 스캔!!

                                    find_orang_x_y = recp_orang.findall(token_str)

                                    for idx_x_y in find_orang_x_y:

                                        if idx_x_y:

                                            print(list(idx_x_y), end = '')

                                            print(' ' + list(idx_x_y)[0] + '/' + list(idx_x_y)[1] + ' : 오랑캐 좌표 발견!!')

                                            # 정찰 시도!!

                                            ret_scout = do_scout(list(idx_x_y)[0], list(idx_x_y)[1])

                                            if ret_scout == 'OK':

                                                f_orang.write('[' + list(idx_x_y)[0] + ',' + list(idx_x_y)[1] + ',정찰시도성공]\n')

                                            else:

                                                f_orang.write('[' + list(idx_x_y)[0] + ',' + list(idx_x_y)[1] + ',정찰시도실패]\n')


                                            findout_cnt += 1

                                    # 식량창고(대) 스캔!!

                                    find_food_x_y = recp_food.findall(token_str)

                                    for idx_x_y in find_food_x_y:

                                        if idx_x_y:

                                            print(list(idx_x_y), end = '')

                                            print(' 미점령 식량창고(대) 좌표 발견!!')

                                            f_food.write(str(idx_x_y) + '\n')

                        else:

                            print('찾은 오랑캐 좌표수 : ' + str(findout_cnt-1) + ', 제한 오랑캐 좌표수 : ' + str(max_findout_cnt) + '\r\n사용자 탐색 제한값에 도달하여 탐색을 중지합니다!!')

                            print('찾아진 오랑캐 좌표가 ''orang_dat.dat''파일로 저장되었습니다!')

                            return '0'

        return '0'

        print('찾아진 오랑캐 좌표가 ''orang_dat.dat''파일로 저장되었습니다!')

        f_orang.close()

        f_food.close()


def get_enemy_info_from_file():

    # 파일오픈..

    try:

        f_new = open('orang_final.dat', 'w')

    except Exception:

        print('오랑캐 좌표 분석을 위한 파일을 여는데 실패하였습니다!!')

        return '::ERROR::'

    

    try:

        # 편지함 뒤지기(의미 없음!!) 

        # 로그패턴을 최대한 실제 어플과 비슷하게 하여 오토 검출을 방해하기 위함

        # (해봐야 맘먹고 찾으면 다 걸리겠지만 ㅋㅋ)

        viewmail_url = '/game/message_api.php?jsonpcallback=jsonp' + get_time() + '&_=' + get_time() + '&key=' + base_token + '&page=1&_l=kr&_p=SG-IPHONE-KR{}HTTP/1.1'.format(urllib.parse.quote(' '))

        html_source = get_html_response(viewmail_url, 2)

        if html_source == '::ERROR::':

            return '::ERROR::'

        if '"code":0' in html_source:

            pass

        else:

            print('정찰 정보를 추출 하는데 실패하였습니다.')

            print('viewmail_url : ' + html_source)

            return '::ERROR::'

        rand_timesleep()

        

        # 정찰결과 리스팅

        scout_info_dat = ''

        while True:

            scout_list_url = '/game/war_result_list_api.php?jsonpcallback=jsonp' + get_time() + '&_=' + get_time() + '&key=' + base_token + '&page=1&type=3&_l=kr&_p=SG-IPHONE-KR{}HTTP/1.1'.format(urllib.parse.quote(' '))

            html_source = get_html_response(scout_list_url, 2)

            if html_source == '::ERROR::':

                return '::ERROR::'

            rand_timesleep()

            if '"code":0' in html_source:

                scout_info_dat = html_source

                # 현재 추출되어진 ID들을 결과함에서 삭제함.. 페이지가 10page 맥스이고 뒤로 밀려 어쩔수 없음..

                scout_del_id = re.findall('"id":(\d+),', html_source)

                

                # 편지함에 저장된 정찰정보의 해당 좌표(정찰이 성공한 좌표만)별 ID값 추출

                if len(scout_del_id):

                    # 제대로 검출 되면!!

                    for list_item in scout_del_id:

                        print('검출된 ID : ' + list_item)

                        point_x = re.search('{"id":' + list_item + ',.+?"dx":(\d+),"dy":(\d+),', scout_info_dat).group(1)

                        point_y = re.search('{"id":' + list_item + ',.+?"dx":(\d+),"dy":(\d+),', scout_info_dat).group(2)

                        print('point_x : ' + point_x + ', point_y : ' + point_y)

                        scout_detail_url = '/game/war_result_info_api.php?jsonpcallback=jsonp' + get_time() + '&_=' + get_time() + '&key=' + base_token + '&id=' + str(list_item) + '&_l=kr&_p=SG-IPHONE-KR{}HTTP/1.1'.format(urllib.parse.quote(' '))

                        html_source = get_html_response(scout_detail_url, 2)

                        if html_source == '::ERROR::':

                            return '::ERROR::'

                        if '"code":0' in html_source:

                            str_token = str(html_source)

                            if '\\uc0b0\\ub3c4\\uc801' in str_token:

                                san_num = '1'

                            else:

                                san_num = '0'

                            if '\\ud654\\uc801' in str_token:

                                hwa_num = '1'

                            else:

                                hwa_num = '0'

                            write_str = '[' + point_x + ',' + point_y + ',' + '산도적(' + san_num + '),화적(' + hwa_num + ')]' 

                            print(write_str)

                            f_new.write(write_str + '\n')

                            rand_timesleep()

                            if int(hwa_num) == 0 and int(san_num) > 0:

                                add_friend_url = '/game/api_fav.php?jsonpcallback=jsonp' + get_time() + '&_=' + get_time() + '&key=' + base_token + '&act=addreport&wid=' + str(list_item) + '&cat=2&_l=kr&_p=SG-IPHONE-KR{}HTTP/1.1'.format(urllib.parse.quote(' '))

                                html_source = get_html_response(add_friend_url, 2)

                                if html_source == '::ERROR::':

                                    return '::ERROR::'

                                if '"code":0' in html_source:

                                    print(write_str + 'Only 산도적 오랑캐 ==> 친구추가완료!!')

                                else:

                                    print(write_str + 'Only 산도적 오랑캐 ==> 친구추가실패!!')

                                    print('add_friend_url : ' + html_source)

                                rand_timesleep()

                        else:

                            print('scout_detail_url Error : ' + html_source)

                else:

                    print('[' + point_x + '/' + point_y + '] 병력상세정보 검출 실패!!')

                    print('scout_detail_url : ' + scout_detail_url)


                if len(scout_del_id):

                    del_str = ''

                    del_id_cnt = len(scout_del_id)

                    while len(scout_del_id):

                        del_pop_item = str(scout_del_id.pop())

                        if len(scout_del_id) == 0:

                            del_str += del_pop_item

                        else:

                            del_str += del_pop_item + '%2C'

                    scout_del_url = '/game/war_result_list_api.php?jsonpcallback=jsonp' + get_time() + '&_=' + get_time() + '&key=' + base_token + '&action=delete&id=' + del_str + '&_l=kr&_p=SG-IPHONE-KR{}HTTP/1.1'.format(urllib.parse.quote(' '))

                    #print('scout_del_url : ' + scout_del_url)

                    html_source = get_html_response(scout_del_url, 2)

                    if html_source == '::ERROR::':

                        return '::ERROR::'

                    rand_timesleep()

                    if '"code":0' in html_source:

                        print('정찰완료 정보' + str(del_id_cnt) + '개 삭제 완료!!')

                    else:

                        print('정찰완료 정보' + str(del_id_cnt) + '개 삭제 실패!!')

                        print('scout_del_url : ' + scout_del_url)

                    print('다음 정찰결과 정보 추출..')

                else:

                    print('모든 정찰결과 정보 추출 완료!!')

                    break

            else:

                print('정찰결과 리스트를 불러오는데 실패하였습니다. 프로그램을 종료합니다!!')

                print('Error Code : ' + html_source)

                return '::ERROR::'


    finally:

        print('정찰결과 분석 정보가 ''orang_final.dat''에 저장되었습니다!!')

        f_new.close()


# 메인함수 시작!!


# 장소 인증

chk_auth()


print("""

***************************************************************

손바닥삼국지 도우미 Ver 0.31(alpha) - by hElLoOnG(2012.04.02)

***************************************************************

*주의사항

*이 프로그램 사용으로 인하여 발생하는 불이익에 대하여

*개발자는 어떠한 책임도 지지 않습니다.

*

*기타 문의 및 버그 수정 요청은 살포시 넣어둬 주세요 ㅋㅋ 

***************************************************************

""")


# 쿠키 생성

base_cookie = make_cookie()

print('Session 생성 : ' + base_cookie)


# 사용자 아이디/패스워드 입력부(입력안하면 기본 아이디로 진행)

temp_user_id = input('손바닥삼국지 ID : ')

if str(temp_user_id).strip() != '':

    base_user_id = temp_user_id

    print('입력된 사용자 ID : ' + base_user_id)

else:

    print('ID가 입력되지 않았습니다!!')

    sys.exit()

temp_user_pw = input('손바닥삼국지 PW : ')

if str(temp_user_pw).strip() != '':

    base_user_pw = temp_user_pw

    print('입력된 사용자 PW : ' + base_user_pw)

else:

    print('PW가 입력되지 않았습니다!!')

    sys.exit()


# 실제 앱에서 일어나는 의미없는 체크

print('손바닥 삼국지 서버로 접속을 시도합니다...')

html_source = attempt_login()

if html_source == '::ERROR::':

    sys.exit()


rand_timesleep()

    

# 사용자 서버 정보 추출

print('사용자의 손바닥 삼국지 서버 정보를 추출합니다...')

get_server_url =  '/info.php?jsonpcallback=jsonp' + get_time() + '&_=' + get_time() + '&user=' + base_user_id + '&action=login&pvp=0&code=a1c1ef3363ae6f52d8e823ecd7d62da618a98c43&_l=kr&_p=SG-IPHONE-KR{}HTTP/1.1'.format(urllib.parse.quote(' '))

html_source = get_html_response(get_server_url, 1)

if html_source == '::ERROR::':

    sys.exit()

if '"code":0' in html_source:

    base_user_host = re.search('k(\d+)\.tapsg\.com', html_source).group()

    print('사용자 서버 추출 성공 : ' + base_user_host)

else:

    print('사용자 서버정보 추출에 실패하였습니다!!\nID, PW를 확인하고 다시 시도하여 주세요!!')

    print('Error Code : ' + html_source)

    sys.exit()


# 실제 인증 키값 추출

print('손바닥 삼국지 인증키 값을 추출합니다...')

login_url = '/game/login_api.php?jsonpcallback=jsonp' + get_time() + '&_=' + get_time() + '&username=' + base_user_id + '&password=' + base_user_pw + '&_l=kr&_p=SG-IPHONE-KR{}HTTP/1.1'.format(urllib.parse.quote(' '))

print('login_url : ' + login_url)

html_source = get_html_response(login_url, 2)

if html_source == '::ERROR::':

    sys.exit()

if '"code":0' in html_source:

    base_token = re.search('key":"(\\w+)"}',html_source).group(1)

    print('사용자 인증키 추출 성공 : ' + base_token)

else:

    print('사용자 인증키 추출에 실패하였습니다!!')

    print('Error Code : ' + html_source)

    sys.exit()


# 사용자 정보 추출

#userinfo_url : jsonp1333982142599({"code":0,"ret":{"user":{"id":20440,"nick":"helloong","nationid":1,"level":39,"money":100,"guild":"\uace0\ud55c\uc74d","guildid":13,"gpower":5,"gflag":64,"protection":0,"p_end":1332411629,"status":0,"city":[{"id":23764,"name":"\ub69d\ub531\uc131","landtype":5,"x":264,"y":133},{"id":24410,"name":"\ub69d\ub531\uc1312","landtype":5,"x":265,"y":133}],"conq":[0,0,null,5],"gift":[],"pvp":0},"events":[{"id":1,"icon":"gem.jpg","name":"\uc131\uc2e4\ud55c \ub2f9\uc2e0\uc744 \uc704\ud55c \ubcf4\uc0c1! [5\/7\uc77c]","desc":"<b>\uc77c\uc77c \uc120\ubb3c<\/b>\uc740 \ub85c\uadf8\uc778 \ud6c4 \ubc1b\uc73c\uc2e4 \uc218 \uc788\uc2b5\ub2c8\ub2e4. 7\uc77c\uac04 \uc5f0\uc18d \ub85c\uadf8\uc778\uc744 \ud558\uc2dc\uba74 <b>\ub3d9\uc6d0\ub839(7\uc77c)<\/b>\uc744 \ub4dc\ub9bd\ub2c8\ub2e4!"},{"id":2,"icon":"0.png","name":"\ub4f1\uae09\uaca9\ucc28 \ubcf4\ud638\uc0c1\ud0dc","desc":"\uba3c\uc800 \uacf5\uaca9\ud558\uc9c0 \uc54a\ub294 \uc774\uc0c1, 10\ub4f1\uae09\uc774\uc0c1\uc758 \uc720\uc800\ub85c\ubd80\ud130 \ubcf4\ud638 \ubc1b\uc2b5\ub2c8\ub2e4. \uc774 \ubcf4\ud638\ub294 \ub85c\uadf8\uc544\uc6c3\ud6c4 24\uc2dc\uac04\uc774 \uc9c0\ub098\uba74 \uc790\ub3d9\uc73c\ub85c \ucde8\uc18c\ub429\ub2c8\ub2e4."}],"status":{"invite":1,"ver":0.9,"vs":1.25,"vr":0.5,"ce":1,"he":1}}})

print('사용자 정보 추출')

userinfo_url = '/game/get_userinfo_api.php?jsonpcallback=jsonp' + get_time() + '&_=' + get_time() + '&key=' + base_token + '&_l=kr&_p=SG-IPHONE-KR{}HTTP/1.1'.format(urllib.parse.quote(' '))

html_source = get_html_response(userinfo_url, 2)

if html_source == '::ERROR::':

    sys.exit()

if '"code":0' in html_source:

    base_city_id = re.search('"city":\[\{"id":(\d+),"name":',html_source).group(1)

    city_id_all  = re.findall('"id":(\d+),"name"', html_source)

    print('사용자 본성 ID : ' + base_city_id)

    print('사용자 전체성 ID : ', end ='')

    print(city_id_all)

else:

    print('사용자 정보 추출에 실패하였습니다!!')

    print('Error Code : ' + html_source)

    sys.exit()


# 사용자 테스크 정보

usertask_url = '/game/system_task_api.php?jsonpcallback=jsonp' + get_time() + '&_=' + get_time() + '&key=' + base_token + '&action=task_list&_l=kr&_p=SG-IPHONE-KR{}HTTP/1.1'.format(urllib.parse.quote(' '))

html_source = get_html_response(usertask_url, 2)

if html_source == '::ERROR::':

    sys.exit()


# 도시정보 호출

city_resource = get_city_resource(base_city_id)

if city_resource == '::ERROR::':

    sys.exit()


# cd 정보??

cdinfo_url = '/game/get_cdinfo_api.php?jsonpcallback=jsonp' + get_time() + '&_=' + get_time() + '&key=' + base_token + '&city=' + base_city_id + '&_l=kr&_p=SG-IPHONE-KR{}HTTP/1.1'.format(urllib.parse.quote(' '))

html_source = get_html_response(cdinfo_url, 2)

if html_source == '::ERROR::':

    sys.exit()


# 사용자 희망 작업 선택!!

print("""

***************************************************************

* 메뉴 선택

***************************************************************

* 1: 오랑캐 좌표 및 현시간 미점령 식량창고(대) 좌표 스캔!!

*    본성에 척후병이 약 100명정도 보유 하셔야 합니다!!

*    초반 성별 식량은 15만 이상 맞춰 주세요!!

*

* 2: ID 정찰결과 함에 존재하는 병력정보 검색(Only산도적 좌표 자동친구추가)

* 3: 도시별 연무장 소문 수집 작업(연무장 레벨 최소 16이상, 고용 공간 필요)

* 4: 친구추가 되어있는 오랑캐 자동사냥

* 5: 종료

***************************************************************


""")


which_way = int(input('원하시는 작업을 선택하여주세요[1 - 4] : '))


if which_way == 1:

    # 오랑캐 추출 갯수 입력부

    base_find_cnt = int(input('얼마나 많은 오랑캐 좌표를 찾길 원하세요?(1-' + str(base_max_cnt) + ') : '))

    if (base_find_cnt < 1) or (base_find_cnt > base_max_cnt):

        print('입력값의 범위가 잘못되었습니다.(입력값은 숫자 1 부터 ' + str(base_max_cnt) + '사이 값이어야 합니다.')

        sys.exit()

    base_find_type = int(input('어떤 종류의 오랑캐를 찾고 싶으세요(1-6)??\n(1:별6개 오랑캐,2:별5개 오랑캐,3:별4개 오랑캐, ...): '))

    if (base_find_type < 1) or (base_find_type > 6):

        print('입력값의 범위가 잘못되었습니다!!(입력값은 숫자 1부터 6사이 값이어야 합니다!!')

        sys.exit()

    point_x = int(input('지도상 x축 스캔시작 좌표 입력[4 - 270](기본값 4) : '))

    if (point_x < 4) or (point_x > 270):

        print('입력값의 범위가 잘못되었습니다!!(입력값은 숫자 4부터 270사이 값이어야 합니다!!')

        sys.exit()

    point_y = int(input('지도상 y축 스캔시작 좌표 입력[4 - 270](기본값 4) : '))

    if (point_y < 4) or (point_y > 270):

        print('입력값의 범위가 잘못되었습니다!!(입력값은 숫자 4부터 270사이 값이어야 합니다!!')

        sys.exit()

    # 지도 스캔 및 오랑캐/식량창고(대) 좌표추출

    print('지도 스캔작업을 시작합니다...')

    ret_val = scan_area_all(base_find_cnt,base_find_type,point_x,point_y)

    if ret_val == '::ERROR::':

        sys.exit()

elif which_way == 2:

    print('입력하신 ID 정찰결과 함으로 부터 병력정보 및 친구추가 작업을 진행합니다...')

    ret_str = get_enemy_info_from_file()

elif which_way == 3:

    print('다음 도시의 연무장에 1시간 5분마다 모든 도시의 한잔하기를 시행합니다!!')

    print('실행중 서버가 불안정 하거나 한잔하기에 필요한 동전이 부족하면 자동 종료됩니다!!')

    print('대상도시 ID : ', end=''); print(city_id_all)

    #GET /game/gen_conscribe_api.php?jsonpcallback=jsonp1333983704456&_=1333983724728&key=c9808b7af18f45e2e6e599ef6a0fcc02&city=23764&_l=kr&_p=SG-IPHONE-KR HTTP/1.1

    #chk_somedrink_url : jsonp1333985951179({"code":0,"ret":{"price":66,"type":3}})

    #GET /game/gen_conscribe_api.php?jsonpcallback=jsonp1333983704457&_=1333983726653&key=c9808b7af18f45e2e6e599ef6a0fcc02&city=23764&action=pub_process&_l=kr&_p=SG-IPHONE-KR HTTP/1.1

    #buy_response : jsonp1334004741746({"code":0,"ret":{"gold":102706,"price":8545,"refresh":3600,"hero":{"gid":205,"p":21,"i":8,"c1":11,"g":3,"c2":300},"rumor":0}})

    #hero gid:아이디, p:공격력, i:지혜력, c1:방어력, c2: 통솔력


    int_drink_tick = 0

    int_mod_sec = 3780 # 1시간 3분


    try:

        f_drink_name = 'drink_log_' + time.strftime('%y%m%d%H%M') + '.dat'

        while True:

            if (int_drink_tick == 0) or (int_drink_tick % int_mod_sec == 0):

                file_drink = open(f_drink_name, 'a')

                for city_id_item in city_id_all:

                    print('현재시간 : ' + time.strftime('%Y-%m-%d %H:%M:%S'))

                    chk_somedrink_url = '/game/gen_conscribe_api.php?jsonpcallback=jsonp' + get_time() + '&_=' + get_time() + '&key=' + base_token + '&city=' + city_id_item + '&_l=kr&_p=SG-IPHONE-KR{}HTTP/1.1'.format(urllib.parse.quote(' '))

                    print('chk_somedrink_url : ' + chk_somedrink_url)

                    html_source = get_html_response(chk_somedrink_url, 2)

                    file_drink.write('chk_somedrink_url : ' + chk_somedrink_url + '\n')

                    if html_source == '::ERROR::':

                        sys.exit()

                    if '"code":0' in html_source:

                        if '"refresh":' in html_source:

                            need_refresh_t = int(re.search('"refresh":(\d+),"hero"', html_source).group(1))

                            print('도시[' + city_id_item + ']의 한잔하기 남은 대기시간 : ' + str(need_refresh_t) + '초 입니다.')

                        else:

                            need_refresh_t = 0

                        need_money = re.search('"price":(\d+),"type"', html_source).group(1)

                        file_drink.write('OK[chk] : ' + str(html_source) + '\n')

                    else:

                        print('도시[' + city_id_item + ']의 소문모으기 준비 작업에 실패하였습니다!!')

                        print('Error Code : ' + html_source)

                        file_drink.write('Err[chk] : ' + str(html_source) + '\n')

                    

                    if need_refresh_t == 0:

                        get_city_money = get_city_resource(city_id_item)

                        print('remain money : ' + get_city_money[0][0] + ', need money : ' + need_money)

                        if int(need_money) > int(get_city_money[0][0]):

                            print('한잔하기에 필요한 동전이 부족하여 작업을 종료합니다!!')

                            sys.exit()

                         

                        buy_somedrink_url = '/game/gen_conscribe_api.php?jsonpcallback=jsonp' + get_time() + '&_=' + get_time() + '&key=' + base_token + '&city=' + city_id_item + '&action=pub_process&_l=kr&_p=SG-IPHONE-KR{}HTTP/1.1'.format(urllib.parse.quote(' '))

                        print('buy_somedrink_url : ' + buy_somedrink_url)

                        html_source = get_html_response(buy_somedrink_url, 2)

                        file_drink.write('buy_somedrink_url : ' + buy_somedrink_url + '\n')

                        if html_source == '::ERROR::':

                            sys.exit()

                        if '"code":0' in html_source:

                            print('buy_response : ' + html_source)

                            file_drink.write('OK[buy] : ' + html_source + '\n')

                        else:

                            print('도시[' + city_id_item + ']의 소문모으기 준비 작업에 실패하였습니다!!')

                            print('Error Code : ' + html_source)

                            file_drink.write('Err[chk] : ' + str(html_source) + '\n')

    

                int_drink_tick = 0

                int_drink_tick += 1

                

                time.sleep(1)

                file_drink.close()

            else:

                #print('현재시간 : ' + time.strftime('%Y-%m-%d %H:%M:%S'))

                int_drink_tick += 1

                #print('남은대기 초 : ' + str(int_drink_tick) + '/' + str(int_mod_sec))

                time.sleep(1)

    finally:

        file_drink.close()

elif which_way == 110:

    while True:

        print('사용자 인증키 : ' + base_token)

        print('현재시간_1 : ' + get_time())

        print('현재시간_2 : ' + get_time())

        print('사용자 본성 ID : ' + base_city_id)

        print('사용자 전체성 ID : ', end ='')

        print(city_id_all)

        input_send_str = str(input('send_str(quit is "q") : '))

        if len(input_send_str) > 1:

            input_send_str = input_send_str.format(urllib.parse.quote(' '))

        if input_send_str == 'q':

            break

        html_source = get_html_response(input_send_str, 2)

        if html_source == '::ERROR::':

            sys.exit()

        print('Response : ')

        print(html_source)

    print('테스트 종료!!')

elif which_way == 4:

    

    city_id_loop = ''

    

    # 질문1

    # 오랑캐 타입!! 어떤 오랑캘 잡을지!!

    type_orang = str(input('친구추가된 오랑캐중 어떤 종류의 오랑캐를 공격하고 싶으세요(1-6)??\n(1:별6개, 2:별5개, 3:별4개, 4:별3개, 5:별2개, 6:별1개): '))

    if (type_orang < '1') or (type_orang > '6'):

        print('입력값의 범위가 잘못되었습니다.(입력값은 숫자 1 부터 6사이 값 이어야 합니다.')

        sys.exit()

    # 질문2

    # 공격 병력타입(중보 : 11, 친위 : 15)

    type_soldier = str(input('어떤 병력으로 오랑캐를 공격하시겠습니까??\n(11: 중보병, 15: 친위기병): '))

    if (type_soldier != '11') and (type_soldier != '15'):

        print('입력값의 범위가 잘못되었습니다.(입력값은 11 또는 15 이어야 합니다.')

        sys.exit()

    # 질문3

    # 공격 병력수 100단위로 입력!!(6성 평균 기준 : 중보 : 800, 친위 : 500)

    num_soldier = int(input('몇명의 병력을 공격에 동원하고 싶으세요\n(100단위 입력, 최소300-최대800): '))

    if (num_soldier < 300) or (num_soldier > 800):

        print('입력값의 범위가 잘못되었습니다!!(입력값은 숫자 300부터 800사이 값이어야 합니다!!')

        sys.exit()

    if (num_soldier % 100) != 0:

        print('입력값의 범위가 잘못되었습니다!!(입력값은 100단위로 이루어져야 합니다!!')

        sys.exit()

    

    city_id_loop = copy.deepcopy(city_id_all)


    while city_id_loop:

        # 리스트 마지막 item을 검출!!

        last_city_id = city_id_loop[len(city_id_loop) - 1]

        # 기본대기시간  10분 60초 * 10분 = 600초

        ret_max_timesleep = 600

        

        for idx_city_id in city_id_loop:

            

            print('[' + idx_city_id + ']성의 자동사냥을 시작합니다...')

            

            ret_max_timesleep = auto_attack(idx_city_id, ret_max_timesleep, type_orang, type_soldier, num_soldier)

            # 리턴값 판별!!

            if ret_max_timesleep < 0:

                # 해당 성 자동 사냥 종료

                city_id_loop.pop(city_id_loop.index(idx_city_id))

                print('[' + idx_city_id + ']성은 자동사냥 목록에서 제외됩니다.')

            else:

                if idx_city_id == last_city_id:

                    print('자동사냥 목록에 있는 모든 성의 자동 사냥 턴이 완료 되었습니다!!')

                    print('인터벌 대기 후 재시작 합니다!!')

                    timesleep(300)

                else:

                    print('[' + idx_city_id + ']성의 자동사냥 턴이 완료 되었습니다!!')

                    print('다음성[' + city_id_loop[city_id_loop.index(idx_city_id) + 1] + ']의 자동사냥을 시작합니다!!')

                    rand_timesleep()

    print('자동 사냥 목록에 남은 성이 없습니다!!')

    input('아무키나 누르시면 자동사냥을 종료합니다.')

    sys.exit()


    # 12. 동전 동괴화 작업!!

    #GET /game/get_userinfo_api.php?jsonpcallback=jsonp1334481191259&_=1334481287964&key=a79a44877dece79457f4e78152c3b08f&action=exp&_l=kr&_p=SG-IPHONE-KR HTTP/1.1

    #GET /game/get_userinfo_api.php?jsonpcallback=jsonp1334481191260&_=1334481290297&key=a79a44877dece79457f4e78152c3b08f&action=g_cd&_l=kr&_p=SG-IPHONE-KR HTTP/1.1

    #GET /game/gold_local_market_api.php?jsonpcallback=jsonp1334481191261&_=1334481299554&key=a79a44877dece79457f4e78152c3b08f&city=23764&type=2&num=1&_l=kr&_p=SG-IPHONE-KR HTTP/1.1


elif which_way == 5:

    print('손바닥삼국지 도우미를 종료합니다.')

    sys.exit()


'Study > python' 카테고리의 다른 글

wxpython webview test  (0) 2013.10.05
[연습중]MK RSS 파싱  (0) 2013.09.23
[연습]Python regular expression & sqlite  (0) 2013.09.22
[펌]Unicode In Python, Completely Demystified  (0) 2013.09.18
python ODBC 연결시~  (0) 2013.01.26
Posted by 땡보