示例#1
0
def current_line(update: Update, context: CallbackContext):
    try:
        sub = pysrt.open(
            context.chat_data['file'],
            encoding='UTF-8',
        )[context.chat_data['line']]
    except KeyError:
        context.chat_data.clear()
        update.effective_message.reply_text(
            text=get('end_of_file'),
            reply_markup=ReplyMarkup.Download,
        )
        return
    if not sub.text.strip().rstrip():
        update.effective_message.reply_text(get('empty_line'))
    else:
        update.effective_message.reply_text(html.escape(sub.text))
    h = ('0' if len(str(sub.start.hours)) == 1 else '') + str(sub.start.hours)
    m = ('0' if len(str(sub.start.minutes)) == 1 else '') + str(
        sub.start.minutes)
    s = ('0' if len(str(sub.start.seconds)) == 1 else '') + str(
        sub.start.seconds)
    start_time = f'{h}:{m}:{s}'
    update.effective_message.reply_text(
        text=get('line_info').format(
            context.chat_data['line'] + 1,
            start_time,
        ),
        reply_markup=ReplyMarkup.PrevNextEmptyDownload,
    )
示例#2
0
def send(data, terminal):
    SYSTEM = settings.get('system_name')

    if terminal:
        import terminal
        terminal.run(data)
        return
        # terminal interface treats the data
        # in a different way.
    elif 'linux' in SYSTEM:
        import linux as interface
    elif 'windows' in SYSTEM:
        import windows as interface
    else:
        return  # nothing to do here

    if not data:
        data = [strings.get('no_anime')]
    else:
        data = [
            '{title} => {episode} {at} {airtime}'.format(title=chunk[0].title,
                                                         episode=chunk[1],
                                                         airtime=chunk[2],
                                                         at=strings.get('at'))
            for chunk in data
        ]

    interface.run(data)
示例#3
0
def run(data):
    print '{}Anime -'.format(get_code(BOLD, get_bg(BLACK))),

    if not data:
        print '{}{}, {}{}'.format(
            get_code(get_fg(RED), get_bg(BLACK)),
            strings.get('weekdays')[settings.get('weekday')],
            settings.get('date').strftime(settings.get('date_format')),
            reset())
        print '{}{}{}'.format(get_code(BOLD, get_fg(RED), get_bg(BLACK)),
                              strings.get('no_anime'), reset())
    else:
        # get length of the biggest title
        tmaxlen = max(len(d[0].title) for d in data)
        # and the length of the biggest episode string
        emaxlen = max(len(d[1]) for d in data)

        print '{}{}, {}{}'.format(
            get_code(get_fg(GREEN), get_bg(BLACK)),
            strings.get('weekdays')[settings.get('weekday')],
            settings.get('date').strftime(settings.get('date_format')),
            reset())
        for chunk in data:
            print('{}{:%is}{} =>' % tmaxlen).format(
                get_code(BOLD, get_fg(GREEN), get_bg(BLACK)), chunk[0].title,
                get_code(reset_fg())),
            print('{}{:%is}{} {}' % emaxlen).format(get_code(get_fg(YELLOW)),
                                                    chunk[1],
                                                    get_code(reset_fg()),
                                                    strings.get('at')),
            print '{}{}{}'.format(get_code(get_fg(CYAN)), chunk[2], reset())
示例#4
0
def parse(file, id):
    data = file.read(length)
    try:
        values = unpack(format, data)
    except:
        return None

    object = {}

    kind = values[0]
    if kind == 0:
        object["kind"] = "no point"
    elif kind == 1:
        object["kind"] = "object"
        sub = unpack("> i ?xxx", values[1])
        object["object id"] = sub[0]
        object["visible"] = sub[1]
    elif kind == 2:
        object["kind"] = "absolute"
    else:
        object["kind"] = "freestanding"

    object["range"] = {"y": values[2], "x": values[3]}

    object["title"] = strings.get(values[4], values[5] - 1)
    object["content"] = strings.get(values[6])
    return object
def on_language_received(update,context):
    current_chat=get_admin_current_chat(update.effective_user.id)
    set_chat_language(current_chat,LANGUAGE_CODES[update.effective_message.text])
    CHAT_TO_LANGUAGE[current_chat]=LANGUAGE_CODES[update.effective_message.text]
    update.effective_message.reply_text(strings.get(strings.language_has_been_set,update),
                                        reply_markup=ReplyKeyboardRemove())
    if update.effective_message.text not in COMPLETE_LANGUAGES:
        update.effective_message.reply_text(strings.get(strings.language_not_complete,update))
    return ConversationHandler.END
def settings(update,context):
    user=update.effective_user
    chat=update.effective_chat
    bot=context.bot
    set_admin_current_chat(user.id)
    update.effective_message.reply_text(strings.get(strings.go_to_private,chat))
    bot.send_message(user.id,strings.get(strings.current_group,user.language_code,
                                         chat.title))
    bot.send_message(user.id,strings.get(strings.select_setting,user.language_code),
                     reply_markup=create_settings_keyboard(user.language_code))
示例#7
0
def run(data):
    summary = '"Anime - {}, {}"'.format(
        strings.get('weekdays')[settings.get('weekday')],
        settings.get('date').strftime(settings.get('date_format')))
    text = '\\n'.join(data).replace('"', r'\"')

    critical = '' if text == strings.get('no_anime') else '-u critical'

    os.system('notify-send -i "%s" %s %s "%s"' %
              (settings.get('icon'), critical, summary, text))
示例#8
0
def support_button(update, context): #TODO forward messages and reply to them
    user=update.effective_user
    query=update.callback_query
    query.answer()
    keyboard=[[InlineKeyboardButton(emojize(strings.get(strings.back_button,update),use_aliases=True),
                                    callback_data='back')]]
    reply_markup=InlineKeyboardMarkup(keyboard)
    query.edit_message_text(
        text=emojize(strings.get(strings.support_button_message,update), use_aliases=True),
        reply_markup=reply_markup
        )
def commands_private(update, context):
    user = update.effective_user
    query = update.callback_query
    query.answer()
    keyboard = [[InlineKeyboardButton(emoji.emojize(strings.get(strings.back_button,update), use_aliases="True"), callback_data="back")]]
    reply_markup = InlineKeyboardMarkup(keyboard)
    query.edit_message_text(
        text = emoji.emojize(strings.get(strings.commands_list, update), use_aliases="True"),
        reply_markup = reply_markup,
        parse_mode= "HTML"
    )
示例#10
0
def ban(update, context):  # TODO until_date, button to unban
    chat = update.effective_chat
    bot = context.bot
    user_to_ban = update.effective_message.reply_to_message.from_user
    reason = ' '.join(context.args)  # FIXME when until_date is added as option
    bot.kick_chat_member(chat.id, user_to_ban.id)
    update.effective_message.reply_text(strings.get(
        strings.user_has_been_banned, chat,
        escape_markdown(user_to_ban.first_name, version=2) +
        ('\n' + strings.get(strings.reason, chat, reason) if reason else '')),
                                        parse_mode=ParseMode.MARKDOWN_V2)
def ban(update, context):  # TODO until_date, button to unban
    chat = update.effective_chat
    bot = context.bot
    user_to_ban = update.effective_message.reply_to_message.from_user
    reason = ' '.join(context.args)  # FIXME when until_date is added as option
    bot.kick_chat_member(chat.id, user_to_ban.id)
    update.effective_message.reply_text(
        strings.get(strings.user_has_been_banned, chat,
                    user_to_ban.mention_html()) + '\n' +
        (strings.get(strings.reason, chat, escape(reason, True))
         if reason else ''),
        parse_mode=ParseMode.HTML)
示例#12
0
def info_button(update, context):
    user=update.effective_user
    query=update.callback_query
    query.answer()
    keyboard=[[InlineKeyboardButton(emojize(strings.get(strings.back_button,update),use_aliases=True),
                                    callback_data='back')]]
    reply_markup=InlineKeyboardMarkup(keyboard)
    query.edit_message_text(
        text=emojize(strings.get(strings.info_button,update,user.first_name,context.bot.get_me().first_name), use_aliases=True),
        reply_markup=reply_markup,
        parse_mode=ParseMode.HTML,
        disable_web_page_preview=True
        )
def start(update,context):
    user = update.effective_user
    mex = update.effective_message
    chat=update.effective_chat
    keyboard = [[InlineKeyboardButton(emoji.emojize(strings.get(strings.add_to_a_group,update), use_aliases="True"), url="https://t.me/SmartGroupGuardianBot?startgroup=start")],
    [InlineKeyboardButton(emoji.emojize(strings.get(strings.commands_private, update), use_aliases="True"), callback_data="commands_private")]]
    reply_markup = InlineKeyboardMarkup(keyboard)
    update.effective_message.reply_text(strings.get(strings.private_start_message,update),
                                            reply_markup = reply_markup)
    if mex.text == "/start":
        pass
    else:
        context.bot.delete_message(chat_id=user.id, message_id=mex.message_id)
def create_settings_keyboard(language):
    return InlineKeyboardMarkup([
        [
            InlineKeyboardButton(strings.get(strings.set_language_button,language),callback_data='set_language'),
            InlineKeyboardButton(strings.get(strings.set_welcome_button,language),callback_data='set_welcome')
        ],
        [
            InlineKeyboardButton(strings.get(strings.set_rules_button,language),callback_data='set_rules'),
            InlineKeyboardButton(strings.get(strings.set_macros_button,language),callback_data='set_macros')
        ],
        [
            InlineKeyboardButton(strings.get(strings.set_warn_button,language),callback_data='set_warn')
        ]
    ])
示例#15
0
 def wrapper(update, context):
     target_id = update.effective_message.reply_to_message.from_user.id
     user_id = update.effective_message.from_user.id
     bot_id = context.bot.get_me().id
     if target_id not in (user_id, bot_id):
         return func(update, context)
     if target_id == user_id:
         update.effective_message.reply_text(
             strings.get(strings.cannot_perform_on_you,
                         update.effective_chat))
     elif target_id == bot_id:
         update.effective_message.reply_text(
             strings.get(strings.cannot_perform_on_me,
                         update.effective_chat))
def alert_admin(update, context):
    chat = update.effective_chat
    admins = context.bot.get_chat_administrators(chat.id)
    for admin in admins:
        try:
            context.bot.send_message(admin.user.id,
                                     strings.get(
                                         strings.user_needs_help, chat,
                                         update.effective_user.first_name,
                                         update.effective_message.link),
                                     parse_mode=ParseMode.HTML)
        except:
            pass
    update.effective_message.reply_text(
        strings.get(strings.admins_have_been_notified, chat))
示例#17
0
 def wrapper(update, context):
     if not is_admin(update.effective_message.reply_to_message.from_user.id,
                     update.effective_chat.id, context.bot):
         return func(update, context)
     update.effective_message.reply_text(
         strings.get(strings.cannot_perform_on_admin,
                     update.effective_chat))
示例#18
0
def on_warn_limit_received(update, context):
    set_warn_limit(get_admin_current_chat(update.effective_user.id),
                   int(update.effective_message.text))
    update.effective_message.reply_text(
        strings.get(strings.ask_for_warn_limit_action, update),
        reply_markup=ReplyKeyboardMarkup(WARN_LIMIT_ACTIONS))
    return WAITING_FOR_WARN_LIMIT_ACTION
示例#19
0
def kick(update, context):
    chat = update.effective_chat
    bot = context.bot
    user_to_kick = update.effective_message.reply_to_message.from_user
    reason = ' '.join(context.args)
    if is_banned(user_to_kick.id, chat.id, bot):
        return update.effective_message.reply_text(
            strings.get(strings.user_is_not_member, chat,
                        user_to_kick.first_name))
    bot.kick_chat_member(chat.id, user_to_kick.id)
    bot.unban_chat_member(chat.id, user_to_kick.id)
    update.effective_message.reply_text(strings.get(
        strings.user_has_been_kicked, chat,
        escape_markdown(user_to_kick.first_name, version=2) +
        ('\n' + strings.get(strings.reason, chat, reason) if reason else '')),
                                        parse_mode=ParseMode.MARKDOWN_V2)
示例#20
0
def on_warn_limit_action_received(update, context):
    set_warn_limit_action(get_admin_current_chat(update.effective_user.id),
                          update.effective_message.text)
    update.effective_message.reply_text(strings.get(
        strings.warn_settings_have_been_set, update),
                                        reply_markup=ReplyKeyboardRemove())
    return ConversationHandler.END
示例#21
0
def start(update,context):
    user=update.effective_user
    mex=update.effective_message
    chat=update.effective_chat
    keyboard=[[InlineKeyboardButton(emojize(strings.get(strings.add_to_a_group,update),use_aliases=True),
                                    url=f'https://t.me/{context.bot.get_me().username}?startgroup=start')],
                [InlineKeyboardButton(emojize(strings.get(strings.support_button,update),use_aliases=True),
                                    callback_data="support"),
                 InlineKeyboardButton(emojize(":information_source:Info",use_aliases=True),
                                    callback_data="info")]   ,
              [InlineKeyboardButton(emojize(strings.get(strings.commands_private,update),use_aliases=True),
                                    callback_data='commands_private')]]
    reply_markup=InlineKeyboardMarkup(keyboard)
    update.effective_message.reply_text(strings.get(strings.private_start_message,update),
                                        reply_markup=reply_markup)
    if mex.text!='/start':
        context.bot.delete_message(user.id,mex.message_id)
示例#22
0
 def wrapper(update, context):
     if is_member(update.effective_message.reply_to_message.from_user.id,
                  update.effective_chat.id, context.bot):
         return func(update, context)
     update.effective_message.reply_text(
         strings.get(
             strings.user_is_not_member, update.effective_chat, update.
             effective_message.reply_to_message.from_user.first_name))
def kick(update, context):
    chat = update.effective_chat
    bot = context.bot
    user_to_kick = update.effective_message.reply_to_message.from_user
    reason = ' '.join(context.args)
    if is_banned(user_to_kick.id, chat.id, bot):
        return update.effective_message.reply_text(strings.get(
            strings.user_is_not_member, chat, user_to_kick.mention_html()),
                                                   parse_mode=ParseMode.HTML)
    bot.kick_chat_member(chat.id, user_to_kick.id)
    bot.unban_chat_member(chat.id, user_to_kick.id)
    update.effective_message.reply_text(
        strings.get(strings.user_has_been_kicked, chat,
                    user_to_kick.mention_html()) + '\n' +
        (strings.get(strings.reason, chat, escape(reason, True))
         if reason else ''),
        parse_mode=ParseMode.HTML)
示例#24
0
def unmute(update, context):
    chat = update.effective_chat
    bot = context.bot
    user_to_unmute = update.effective_message.reply_to_message.from_user
    bot.restrict_chat_member(chat.id, user_to_unmute.id,
                             bot.get_chat(chat.id).permissions)
    update.effective_message.reply_text(
        strings.get(strings.user_has_been_unmuted, chat,
                    user_to_unmute.first_name))
示例#25
0
def new(update: Update, context: CallbackContext):
    args = update.effective_message.text.split()
    if len(args) != 3:
        update.effective_message.reply_text(get('usage_of_new_command'))
        return
    try:
        start = pysrt.srttime.SubRipTime.from_string(args[1])
        end = pysrt.srttime.SubRipTime.from_string(args[2])
    except pysrt.srttime.InvalidTimeString:
        update.effective_message.reply_text(get('invalid_time_provided'))
        return
    file = pysrt.open(context.chat_data['file'], encoding='UTF-8')
    file.append(pysrt.srtitem.SubRipItem(start=start, end=end))
    file.clean_indexes()
    file.save(context.chat_data['file'], encoding='UTF-8')
    context.chat_data['line'] = 0
    update.effective_message.reply_text(get('line_added'))
    send.current_line(update, context)
def unmute(update, context):
    chat = update.effective_chat
    bot = context.bot
    user_to_unmute = update.effective_message.reply_to_message.from_user
    bot.restrict_chat_member(chat.id, user_to_unmute.id,
                             bot.get_chat(chat.id).permissions)
    update.effective_message.reply_text(strings.get(
        strings.user_has_been_unmuted, chat, user_to_unmute.mention_html()),
                                        parse_mode=ParseMode.HTML)
def mute(update, context):  # TODO until_date, button to unmute
    chat = update.effective_chat
    bot = context.bot
    user_to_mute = update.effective_message.reply_to_message.from_user
    bot.restrict_chat_member(chat.id, user_to_mute.id,
                             ChatPermissions(can_send_messages=False))
    update.effective_message.reply_text(strings.get(
        strings.user_has_been_muted, chat, user_to_mute.mention_html()),
                                        parse_mode=ParseMode.HTML)
示例#28
0
def parse(file, id = None):
	data = file.read(length)
	try:
		values = unpack(format, data)
	except:
		return None
	
	object = {}
	
	object["id"] = values[0]
	#apparent color
	#illegal colors
	object["advantage"] = decode.fixed(values[3])

	object["singular"] = strings.get(4201, 4*id + 0)
	object["plural"] = strings.get(4201, 4*id + 1)
	object["military"] = strings.get(4201, 4*id + 2)
	object["home world"] = strings.get(4201, 4*id + 3)
	return object
示例#29
0
def edit(update: Update, context: CallbackContext):
    file = pysrt.open(context.chat_data['file'], encoding='UTF-8')
    file[context.chat_data['line']].text = get_to_save(
        update.effective_message.text, )
    file.save(context.chat_data['file'], encoding='UTF-8')
    update.effective_message.reply_text(
        text=get('edited'),
        reply_markup=ReplyMarkup.PrevNextEmptyDownload,
    )
    send.next_line(update, context)
示例#30
0
def open(update: Update, context: CallbackContext):
    try:
        file_name = update.effective_message.text.split(maxsplit=1)[1]
    except IndexError:
        update.effective_message.reply_text(get('give_file_name'))
        return
    file_path = path.join(
        path.dirname(path.dirname(__file__), ),
        'files',
        file_name,
    )
    if not path.isfile(file_path):
        update.effective_message.reply_text(get('file_does_not_exist'))
        return
    if not file_path.endswith('.srt'):
        return
    context.chat_data['file'] = file_path
    context.chat_data['line'] = 0
    update.effective_message.reply_text(get('opened'))
    send.current_line(update, context)
示例#31
0
def line(update: Update, context: CallbackContext):
    try:
        line = update.effective_message.text.split(maxsplit=1)[1]
    except IndexError:
        update.effective_message.reply_text(get('give_line_number'))
        return
    try:
        line = int(line) - 1
    except ValueError:
        update.effective_message.reply_text(get('give_line_number'))
        return
    file = pysrt.open(context.chat_data['file'], encoding='UTF-8')
    if line not in range(len(file)):
        update.effective_message.reply_text(
            get('line_x_does_not_exist').format(line + 1), )
        return
    context.chat_data['line'] = line
    update.effective_message.reply_text(
        get('moved_to_line_x').format(line + 1), )
    send.current_line(update, context)
示例#32
0
def search(update: Update, context: CallbackContext):
    try:
        query = update.effective_message.text.split(maxsplit=1)[1].lower()
    except IndexError:
        update.effective_message.reply_text(get('provide_search_query'))
        return
    file = pysrt.open(context.chat_data['file'], encoding='UTF-8')
    results = []
    for i in range(len(file)):
        no, line = i + 1, file[i]
        if len(results) > 10:
            break
        if query in line.text.lower():
            results.append([
                no, html.escape(
                    line.text.lower(),
                ).replace(query, f'<b>{query}</b>'),
            ])
    if len(results) == 0:
        update.effective_message.reply_text(
            text=get('no_results_found'),
            reply_markup=ReplyMarkup.Remove,
        )
        return
    update.effective_message.reply_text(
        text='\n'.join(
            (
                f'<b>{html.escape(result[1])}</b>\n└ {result[0]}'
                for result in results[:10]
            ),
        ),
        reply_markup=ReplyMarkup.Remove,
    )
    update.effective_message.reply_text(
        text=get('x_results_found').format(len(results)) if len(
            results,
        ) != 1 else get('one_result_found'),
    )
    if len(results) > 10:
        update.effective_message.reply_text(get('showing_first_ten_results'))
示例#33
0
def get_strings(filename):
	show_strings = strings.get(filename)
	return show_strings
示例#34
0
def parse(file, id = None):
	data = file.read(size)
	try:
		values = unpack(format, data)
	except:
		return None
	object = {}
	
	object["net race flags"] = values[0]
	object["player num"] = values[1]
	
	object["players"] = {}
	for i in range(0, object["player num"]):
		player = {}
		type = values[2+6*i+0]
		if type == 0:
			player["type"] = "single"
		elif type == 1:
			player["type"] = "net"
		elif type == 2:
			player["type"] = "cpu"

		player["race"] = values[2+6*i+1]
		player["name"] = strings.get(values[2+6*i+2], values[2+6*i+3]- 1)
		#player["admiral number"] = values[2+8*i+4] #unused it seems
		player["earning power"] = decode.fixed(values[2+6*i+4])
		player["net race flags"] = values[2+6*i+5]
		object["players"][i+1] = player
	
	if values[26] > 0:
		object["score string"] = strings.get(values[26], True)
	else:
		object["score string"] = []
	object["initial objects"] = {
			"first": values[27],
			"count": values[29],
			}
	
	object["prologue"] = strings.get(values[28])
	object["epilogue"] = strings.get(values[32])

	object["song id"] = values[30]

	object["conditions"] = {
			"first": values[31],
			"count": values[33],
			}

	object["starmap"] = {
			"x": values[34],
			"y": values[36],
			}

	object["angle"] = values[37]

	object["briefing"] = {
			"first": values[35],
			"count": values[38],
			}

	object["par"] = {
			"time": values[39],
			"kills": values[41],
			"ratio": decode.fixed(values[43]),
			"losses": values[44],
			}

	if values[40] > -1:
		object["movie"] = strings.get(4500, values[40])
	else:
		object["movie"] = None

	object["id"] = values[42]
	object["name"] = strings.get(4600, values[42]-1)

	object["start time"] = 0x7fff & values[45]
	object["is training"] = (0x8000 & values[45]) == True
	return object
示例#35
0
def parse(file, id = None):
	data = file.read(length)
	try:
		values = struct.unpack(format, data)
	except:
		return None

	object = {}

	object["attributes"] = decode.bitfield(values[0], attributes)
	object["class"] = values[1]
	object["race"] = values[2]
	object["price"] = values[3]

	object["offence"] = decode.fixed(values[4])
	object["escort rank"] = values[5]#aka target, aka destination class
	
	object["max velocity"] = decode.fixed(values[6])
	object["warp speed"] = decode.fixed(values[7])
	object["warp out distance"] = values[8]

	object["initial velocity"] = decode.fixed(values[9])
	object["initial velocity range"] = decode.fixed(values[10])

	mass = decode.fixed(values[11])
	if mass == 0:
		mass = 1.0
	object["mass"] = mass
	object["thrust"] = decode.fixed(values[12])

	object["health"] = values[13]
	object["damage"] = values[14]
	object["energy"] = values[15]

	object["initial age"] = values[16]
	object["initial age range"] = values[17] #add occuping force hack

	object["scale"] = values[18] #was natural scale

	object["layer"] = values[19]
	object["sprite id"] = values[20]
	object["icon size"] = 0x0f & values[21]
	try: 
		object["icon shape"] = {
				0x00: "square",
				0x10: "triangle",
				0x20: "diamond",
				0x30: "plus",
				0x40: "framed square"
				}[0x70 & values[21]]
	except KeyError:
		object["icon shape"] = None
	object["shield color"] = values[22]
	
	#**** compiler alignment

	object["initial direction"] = values[23]
	object["initial direction range"] = values[24]

	object["weapons"] = {
			"pulse": {
				"id": values[25],
				"count": values[28],
				"positions": {},
				},
			"beam": {
				"id": values[26],
				"count": values[29],
				"positions": {},
				},
			"special": {
				"id": values[27],
				"count": values[30],
				"positions": {},
				},
			}
	ct = 31
	for weap in ["pulse", "beam", "special"]:
		for idx in range(0, object["weapons"][weap]["count"]):
			object["weapons"][weap]["positions"][idx + 1] = {
						"y": decode.fixed(values[ct+2*idx]),
						"x": decode.fixed(values[ct+2*idx+1]),
					}
		ct += 6
	
	object["friend defecit"] = decode.fixed(values[49])
	object["danger threshold"] = decode.fixed(values[50])

	object["special direction"] = values[51] #unused?

	object["arrive action distance"] = values[52]

	object["actions"] = {
			"destroy": {
				"first": values[53],
				"count": values[54] & 0x7fffffff,
				"dont die on death": bool(values[54] & 0x80000000),
				},
			"expire": {
				"first": values[55],
				"count": values[56],
				},
			"create": {
				"first": values[57],
				"count": values[58],
				},
			"collide": {
				"first": values[59],
				"count": values[60],
				},
			"activate": {
				"first": values[61],
				"count": values[62] & 0x0000ffff,
				"interval": (values[62] & 0xff000000) >> 24,
				"interval range": (values[62] & 0x00ff0000) >> 16,
				},
			"arrive": {
				"first": values[63],
				"count": values[64],
				},
			}
	
	if object["attributes"]["shape from direction"] == True:
		frame = struct.unpack(">iiii 16x", values[65])
		object["rotation"] = {
				"offset": frame[0],
				"resolution": frame[1],
				"turn rate": decode.fixed(frame[2]),
				"turn acceleration": decode.fixed(frame[3]),
				}
	elif object["attributes"]["is self animated"] == True:
		frame = struct.unpack(">8i", values[65])
		object["animation"] = {
			"first shape": frame[0],
			"last shape": frame[1],
			"direction": frame[2],
			"direction range": frame[3],
			"speed": frame[4],
			"speed range": frame[5],
			"shape": frame[6],
			"shape range": frame[7],
			}
	elif object["attributes"]["is beam"] == True:
		frame = struct.unpack(">BBii 22x", values[65])
		object
		if frame[1] == 0:
			object["beam"] = {
				"hex": 0x0, #000
				"type": "kinetic",
				"mode": None,
				}
		elif frame[1] == 1:
			object["beam"] = {
				"hex": 0x2, #010
				"type": "static",
				"mode": "direct",
				}
		elif frame[1] == 2:
			object["beam"] = {
				"hex": 0x3, #011
				"type": "static",
				"mode": "relative",
				}
		elif frame[1] == 3:
			object["beam"] = {
				"hex": 0x4, #100
				"type": "bolt",
				"mode": "direct",
				}
		elif frame[1] == 4:
			object["beam"] = {
				"hex": 0x5, #101
				"type": "bolt",
				"mode": "relative",
				}
		object["beam"]["color"] = frame[0]
		object["beam"]["accuracy"] = frame[2]
		object["beam"]["range"] = math.sqrt(frame[3])
	else: #device
		frame = struct.unpack(">Iiiiiii 4x", values[65])
		object["device"] = {
			"uses": decode.bitfield(frame[0], deviceUses),
			"energy cost": frame[1],
			"reload": frame[2],
			"ammo": frame[3],
			"range": frame[4],
			"inverse speed": frame[5],
			"restock cost": frame[6],
			}
	object["build flags"] = decode.bitfield(values[66], buildFlags)
	object["order flags"] = decode.bitfield(values[67], orderFlags)
	
	object["build ratio"] = decode.fixed(values[68])
	object["build time"] = values[69]

	object["skill num"] = values[70]
	object["skill den"] = values[71]
	object["skill num adj"] = values[72]
	object["skill den adj"] = values[73]
	
	object["portrait id"] = values[74]
	
	if id != None:
		object["name"] = strings.get(5000, id)
		object["short name"] = strings.get(5001, id)
		object["notes"] = strings.get(5002, id)
		object["static name"] = strings.get(5003, id)
	return object